@q1k-oss/btree-workflows 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (206) hide show
  1. package/README.md +13 -13
  2. package/dist/index.cjs +5011 -0
  3. package/dist/index.d.cts +3320 -0
  4. package/dist/index.d.ts +3320 -0
  5. package/dist/index.js +4879 -0
  6. package/package.json +33 -3
  7. package/.claude/settings.local.json +0 -31
  8. package/CLAUDE.md +0 -181
  9. package/behaviour-tree-workflows-landing/index.html +0 -16
  10. package/behaviour-tree-workflows-landing/package-lock.json +0 -2074
  11. package/behaviour-tree-workflows-landing/package.json +0 -31
  12. package/behaviour-tree-workflows-landing/public/favicon.svg +0 -17
  13. package/behaviour-tree-workflows-landing/src/App.css +0 -103
  14. package/behaviour-tree-workflows-landing/src/App.tsx +0 -176
  15. package/behaviour-tree-workflows-landing/src/components/BlackboardInspector.css +0 -89
  16. package/behaviour-tree-workflows-landing/src/components/BlackboardInspector.tsx +0 -64
  17. package/behaviour-tree-workflows-landing/src/components/ExampleSelector.css +0 -64
  18. package/behaviour-tree-workflows-landing/src/components/ExampleSelector.tsx +0 -34
  19. package/behaviour-tree-workflows-landing/src/components/ExecutionLog.css +0 -107
  20. package/behaviour-tree-workflows-landing/src/components/ExecutionLog.tsx +0 -85
  21. package/behaviour-tree-workflows-landing/src/components/Header.css +0 -50
  22. package/behaviour-tree-workflows-landing/src/components/Header.tsx +0 -26
  23. package/behaviour-tree-workflows-landing/src/components/StatusBadge.css +0 -45
  24. package/behaviour-tree-workflows-landing/src/components/StatusBadge.tsx +0 -15
  25. package/behaviour-tree-workflows-landing/src/components/Toolbar.css +0 -74
  26. package/behaviour-tree-workflows-landing/src/components/Toolbar.tsx +0 -53
  27. package/behaviour-tree-workflows-landing/src/components/TreeVisualizer.css +0 -67
  28. package/behaviour-tree-workflows-landing/src/components/TreeVisualizer.tsx +0 -192
  29. package/behaviour-tree-workflows-landing/src/components/YamlEditor.css +0 -18
  30. package/behaviour-tree-workflows-landing/src/components/YamlEditor.tsx +0 -96
  31. package/behaviour-tree-workflows-landing/src/lib/count-nodes.ts +0 -11
  32. package/behaviour-tree-workflows-landing/src/lib/execution-engine.ts +0 -96
  33. package/behaviour-tree-workflows-landing/src/lib/tree-layout.ts +0 -136
  34. package/behaviour-tree-workflows-landing/src/lib/yaml-examples.ts +0 -549
  35. package/behaviour-tree-workflows-landing/src/main.tsx +0 -9
  36. package/behaviour-tree-workflows-landing/src/stubs/activepieces.ts +0 -18
  37. package/behaviour-tree-workflows-landing/src/stubs/fs.ts +0 -24
  38. package/behaviour-tree-workflows-landing/src/stubs/path.ts +0 -16
  39. package/behaviour-tree-workflows-landing/src/stubs/temporal-activity.ts +0 -6
  40. package/behaviour-tree-workflows-landing/src/stubs/temporal-workflow.ts +0 -22
  41. package/behaviour-tree-workflows-landing/tsconfig.json +0 -25
  42. package/behaviour-tree-workflows-landing/vite.config.ts +0 -40
  43. package/demo-google-sheets.ts +0 -181
  44. package/demo-runtime-variables.ts +0 -174
  45. package/demo-template.ts +0 -208
  46. package/docs/ARCHITECTURE_SUMMARY.md +0 -613
  47. package/docs/NODE_REFERENCE.md +0 -504
  48. package/docs/README.md +0 -53
  49. package/docs/custom-nodes-architecture.md +0 -826
  50. package/docs/observability.md +0 -175
  51. package/docs/yaml-specification.md +0 -990
  52. package/examples/temporal/README.md +0 -117
  53. package/examples/temporal/activities.ts +0 -373
  54. package/examples/temporal/client.ts +0 -115
  55. package/examples/temporal/python-worker/activities.py +0 -339
  56. package/examples/temporal/python-worker/requirements.txt +0 -12
  57. package/examples/temporal/python-worker/worker.py +0 -106
  58. package/examples/temporal/worker.ts +0 -66
  59. package/examples/temporal/workflows.ts +0 -6
  60. package/examples/temporal/yaml-workflow-loader.ts +0 -105
  61. package/examples/yaml-test.ts +0 -97
  62. package/examples/yaml-workflows/01-simple-sequence.yaml +0 -25
  63. package/examples/yaml-workflows/02-parallel-timeout.yaml +0 -45
  64. package/examples/yaml-workflows/03-ecommerce-checkout.yaml +0 -94
  65. package/examples/yaml-workflows/04-ai-agent-workflow.yaml +0 -346
  66. package/examples/yaml-workflows/05-order-processing.yaml +0 -146
  67. package/examples/yaml-workflows/06-activity-test.yaml +0 -71
  68. package/examples/yaml-workflows/07-activity-simple-test.yaml +0 -43
  69. package/examples/yaml-workflows/08-file-processing.yaml +0 -141
  70. package/examples/yaml-workflows/09-http-request.yaml +0 -137
  71. package/examples/yaml-workflows/README.md +0 -211
  72. package/src/actions/code-execution.schema.ts +0 -27
  73. package/src/actions/code-execution.ts +0 -218
  74. package/src/actions/generate-file.test.ts +0 -516
  75. package/src/actions/generate-file.ts +0 -166
  76. package/src/actions/http-request.test.ts +0 -784
  77. package/src/actions/http-request.ts +0 -228
  78. package/src/actions/index.ts +0 -20
  79. package/src/actions/parse-file.test.ts +0 -448
  80. package/src/actions/parse-file.ts +0 -139
  81. package/src/actions/python-script.test.ts +0 -439
  82. package/src/actions/python-script.ts +0 -154
  83. package/src/base-node.test.ts +0 -511
  84. package/src/base-node.ts +0 -605
  85. package/src/behavior-tree.test.ts +0 -431
  86. package/src/behavior-tree.ts +0 -283
  87. package/src/blackboard.test.ts +0 -222
  88. package/src/blackboard.ts +0 -192
  89. package/src/composites/conditional.schema.ts +0 -19
  90. package/src/composites/conditional.test.ts +0 -309
  91. package/src/composites/conditional.ts +0 -129
  92. package/src/composites/for-each.schema.ts +0 -23
  93. package/src/composites/for-each.test.ts +0 -254
  94. package/src/composites/for-each.ts +0 -132
  95. package/src/composites/index.ts +0 -15
  96. package/src/composites/memory-sequence.schema.ts +0 -19
  97. package/src/composites/memory-sequence.test.ts +0 -223
  98. package/src/composites/memory-sequence.ts +0 -98
  99. package/src/composites/parallel.schema.ts +0 -28
  100. package/src/composites/parallel.test.ts +0 -502
  101. package/src/composites/parallel.ts +0 -157
  102. package/src/composites/reactive-sequence.schema.ts +0 -19
  103. package/src/composites/reactive-sequence.test.ts +0 -170
  104. package/src/composites/reactive-sequence.ts +0 -85
  105. package/src/composites/recovery.schema.ts +0 -19
  106. package/src/composites/recovery.test.ts +0 -366
  107. package/src/composites/recovery.ts +0 -90
  108. package/src/composites/selector.schema.ts +0 -19
  109. package/src/composites/selector.test.ts +0 -387
  110. package/src/composites/selector.ts +0 -85
  111. package/src/composites/sequence.schema.ts +0 -19
  112. package/src/composites/sequence.test.ts +0 -337
  113. package/src/composites/sequence.ts +0 -72
  114. package/src/composites/sub-tree.schema.ts +0 -21
  115. package/src/composites/sub-tree.test.ts +0 -893
  116. package/src/composites/sub-tree.ts +0 -177
  117. package/src/composites/while.schema.ts +0 -24
  118. package/src/composites/while.test.ts +0 -381
  119. package/src/composites/while.ts +0 -149
  120. package/src/data-store/index.ts +0 -10
  121. package/src/data-store/memory-store.ts +0 -161
  122. package/src/data-store/types.ts +0 -94
  123. package/src/debug/breakpoint.test.ts +0 -47
  124. package/src/debug/breakpoint.ts +0 -30
  125. package/src/debug/index.ts +0 -17
  126. package/src/debug/resume-point.test.ts +0 -49
  127. package/src/debug/resume-point.ts +0 -29
  128. package/src/decorators/delay.schema.ts +0 -21
  129. package/src/decorators/delay.test.ts +0 -261
  130. package/src/decorators/delay.ts +0 -140
  131. package/src/decorators/force-result.schema.ts +0 -32
  132. package/src/decorators/force-result.test.ts +0 -133
  133. package/src/decorators/force-result.ts +0 -63
  134. package/src/decorators/index.ts +0 -13
  135. package/src/decorators/invert.schema.ts +0 -19
  136. package/src/decorators/invert.test.ts +0 -135
  137. package/src/decorators/invert.ts +0 -42
  138. package/src/decorators/keep-running.schema.ts +0 -20
  139. package/src/decorators/keep-running.test.ts +0 -105
  140. package/src/decorators/keep-running.ts +0 -49
  141. package/src/decorators/precondition.schema.ts +0 -19
  142. package/src/decorators/precondition.test.ts +0 -351
  143. package/src/decorators/precondition.ts +0 -139
  144. package/src/decorators/repeat.schema.ts +0 -21
  145. package/src/decorators/repeat.test.ts +0 -187
  146. package/src/decorators/repeat.ts +0 -94
  147. package/src/decorators/run-once.schema.ts +0 -19
  148. package/src/decorators/run-once.test.ts +0 -140
  149. package/src/decorators/run-once.ts +0 -61
  150. package/src/decorators/soft-assert.schema.ts +0 -19
  151. package/src/decorators/soft-assert.test.ts +0 -107
  152. package/src/decorators/soft-assert.ts +0 -68
  153. package/src/decorators/timeout.schema.ts +0 -21
  154. package/src/decorators/timeout.test.ts +0 -274
  155. package/src/decorators/timeout.ts +0 -159
  156. package/src/errors.test.ts +0 -63
  157. package/src/errors.ts +0 -34
  158. package/src/events.test.ts +0 -347
  159. package/src/events.ts +0 -183
  160. package/src/index.ts +0 -80
  161. package/src/integrations/index.ts +0 -30
  162. package/src/integrations/integration-action.test.ts +0 -571
  163. package/src/integrations/integration-action.ts +0 -233
  164. package/src/integrations/piece-executor.ts +0 -320
  165. package/src/observability/execution-tracker.ts +0 -320
  166. package/src/observability/index.ts +0 -23
  167. package/src/observability/sinks.ts +0 -138
  168. package/src/observability/types.ts +0 -130
  169. package/src/registry-utils.ts +0 -147
  170. package/src/registry.test.ts +0 -466
  171. package/src/registry.ts +0 -334
  172. package/src/schemas/base.schema.ts +0 -104
  173. package/src/schemas/index.ts +0 -223
  174. package/src/schemas/integration.test.ts +0 -238
  175. package/src/schemas/tree-definition.schema.ts +0 -170
  176. package/src/schemas/validation.test.ts +0 -146
  177. package/src/schemas/validation.ts +0 -122
  178. package/src/scripting/index.ts +0 -22
  179. package/src/templates/template-loader.test.ts +0 -281
  180. package/src/templates/template-loader.ts +0 -152
  181. package/src/temporal-integration.test.ts +0 -213
  182. package/src/test-nodes.ts +0 -259
  183. package/src/types.ts +0 -503
  184. package/src/utilities/index.ts +0 -17
  185. package/src/utilities/log-message.test.ts +0 -275
  186. package/src/utilities/log-message.ts +0 -134
  187. package/src/utilities/regex-extract.test.ts +0 -138
  188. package/src/utilities/regex-extract.ts +0 -108
  189. package/src/utilities/variable-resolver.test.ts +0 -416
  190. package/src/utilities/variable-resolver.ts +0 -318
  191. package/src/utils/error-handler.test.ts +0 -117
  192. package/src/utils/error-handler.ts +0 -48
  193. package/src/utils/signal-check.test.ts +0 -234
  194. package/src/utils/signal-check.ts +0 -140
  195. package/src/yaml/errors.ts +0 -143
  196. package/src/yaml/index.ts +0 -30
  197. package/src/yaml/loader.ts +0 -39
  198. package/src/yaml/parser.ts +0 -286
  199. package/src/yaml/validation/semantic-validator.ts +0 -196
  200. package/templates/google-sheets/insert-row.yaml +0 -76
  201. package/templates/notification-sender.yaml +0 -33
  202. package/templates/order-validation.yaml +0 -44
  203. package/tsconfig.json +0 -24
  204. package/vitest.config.ts +0 -25
  205. package/workflows/order-processor.yaml +0 -59
  206. package/workflows/process-order-workflow.yaml +0 -142
@@ -1,157 +0,0 @@
1
- /**
2
- * Parallel composite node
3
- * Executes all children concurrently (truly concurrent, not sequential)
4
- */
5
-
6
- import { CompositeNode } from "../base-node.js";
7
- import {
8
- type TemporalContext,
9
- type NodeConfiguration,
10
- NodeStatus,
11
- } from "../types.js";
12
- import { checkSignal } from "../utils/signal-check.js";
13
-
14
- /**
15
- * Execution strategy for parallel node
16
- */
17
- export type ParallelStrategy =
18
- | "strict" // All children must succeed
19
- | "any"; // At least one child must succeed
20
-
21
- export interface ParallelConfiguration extends NodeConfiguration {
22
- /**
23
- * Execution strategy
24
- * - 'strict': All children must succeed (default)
25
- * - 'any': At least one child must succeed
26
- */
27
- strategy?: ParallelStrategy;
28
-
29
- /**
30
- * Optional: Number of children that must succeed (overrides strategy)
31
- */
32
- successThreshold?: number;
33
-
34
- /**
35
- * Optional: Number of children that must fail before parallel fails
36
- */
37
- failureThreshold?: number;
38
- }
39
-
40
- export class Parallel extends CompositeNode {
41
- private strategy: ParallelStrategy;
42
- private successThreshold?: number;
43
- private failureThreshold?: number;
44
-
45
- constructor(config: ParallelConfiguration) {
46
- super(config);
47
- this.strategy = config.strategy ?? "strict";
48
- this.successThreshold = config.successThreshold;
49
- this.failureThreshold = config.failureThreshold;
50
- }
51
-
52
- async executeTick(context: TemporalContext): Promise<NodeStatus> {
53
- this.log(
54
- `Ticking with ${this._children.length} children (strategy: ${this.strategy})`,
55
- );
56
-
57
- if (this._children.length === 0) {
58
- return NodeStatus.SUCCESS;
59
- }
60
-
61
- // Only tick children that haven't completed yet (IDLE or RUNNING)
62
- // Children that are SUCCESS or FAILURE should keep their status
63
- const childrenToTick = this._children.filter((child) => {
64
- const status = child.status();
65
- return status === NodeStatus.IDLE || status === NodeStatus.RUNNING;
66
- });
67
-
68
- this.log(
69
- `Ticking ${childrenToTick.length}/${this._children.length} children (others completed)`,
70
- );
71
-
72
- // Check for cancellation before concurrent execution
73
- checkSignal(context.signal);
74
-
75
- // Tick active children concurrently using Promise.all
76
- if (childrenToTick.length > 0) {
77
- await Promise.all(childrenToTick.map((child) => child.tick(context)));
78
- }
79
-
80
- // Collect all statuses (from both ticked and already-completed children)
81
- const allStatuses = this._children.map((child) => child.status());
82
-
83
- // Check if any child is still running
84
- const hasRunning = allStatuses.some(
85
- (status) => status === NodeStatus.RUNNING,
86
- );
87
- if (hasRunning) {
88
- this.log("At least one child returned RUNNING");
89
- return NodeStatus.RUNNING;
90
- }
91
-
92
- // All children completed - count successes and failures
93
- const successes = allStatuses.filter(
94
- (status) => status === NodeStatus.SUCCESS,
95
- ).length;
96
- const failures = allStatuses.filter(
97
- (status) => status === NodeStatus.FAILURE,
98
- ).length;
99
-
100
- this.log(`Results - Successes: ${successes}, Failures: ${failures}`);
101
-
102
- // Check threshold-based completion first (if configured)
103
- if (
104
- this.successThreshold !== undefined &&
105
- successes >= this.successThreshold
106
- ) {
107
- this.log(
108
- `Success threshold met: ${successes}/${this.successThreshold} -> SUCCESS`,
109
- );
110
- return NodeStatus.SUCCESS;
111
- }
112
-
113
- if (
114
- this.failureThreshold !== undefined &&
115
- failures >= this.failureThreshold
116
- ) {
117
- this.log(
118
- `Failure threshold met: ${failures}/${this.failureThreshold} -> FAILURE`,
119
- );
120
- return NodeStatus.FAILURE;
121
- }
122
-
123
- // Apply strategy
124
- if (this.strategy === "strict") {
125
- // All must succeed
126
- const finalStatus =
127
- successes === this._children.length
128
- ? NodeStatus.SUCCESS
129
- : NodeStatus.FAILURE;
130
- this.log(
131
- `Strategy 'strict': ${successes}/${this._children.length} succeeded -> ${finalStatus}`,
132
- );
133
- return finalStatus;
134
- } else {
135
- // Any (at least one must succeed)
136
- const finalStatus =
137
- successes > 0 ? NodeStatus.SUCCESS : NodeStatus.FAILURE;
138
- this.log(`Strategy 'any': ${successes} succeeded -> ${finalStatus}`);
139
- return finalStatus;
140
- }
141
- }
142
-
143
- protected onHalt(): void {
144
- this.log("Halting parallel execution");
145
- // Halt all running children
146
- for (const child of this._children) {
147
- if (child.status() === NodeStatus.RUNNING) {
148
- child.halt();
149
- }
150
- }
151
- }
152
-
153
- protected onReset(): void {
154
- this.log("Resetting parallel state");
155
- // Reset handled by parent class
156
- }
157
- }
@@ -1,19 +0,0 @@
1
- /**
2
- * ReactiveSequence composite configuration schema
3
- */
4
-
5
- import { z } from "zod";
6
- import { nodeConfigurationSchema } from "../schemas/base.schema.js";
7
-
8
- /**
9
- * Schema for ReactiveSequence composite configuration
10
- * Uses base schema only (no additional properties)
11
- */
12
- export const reactiveSequenceConfigurationSchema = nodeConfigurationSchema;
13
-
14
- /**
15
- * Validated ReactiveSequence configuration type
16
- */
17
- export type ValidatedReactiveSequenceConfiguration = z.infer<
18
- typeof reactiveSequenceConfigurationSchema
19
- >;
@@ -1,170 +0,0 @@
1
- /**
2
- * Tests for ReactiveSequence node
3
- */
4
-
5
- import { beforeEach, describe, expect, it } from "vitest";
6
- import { ScopedBlackboard } from "../blackboard.js";
7
- import { FailureNode, SuccessNode } from "../test-nodes.js";
8
- import { type TemporalContext, NodeStatus } from "../types.js";
9
- import { ReactiveSequence } from "./reactive-sequence.js";
10
-
11
- describe("ReactiveSequence", () => {
12
- let blackboard: ScopedBlackboard;
13
- let context: TemporalContext;
14
-
15
- beforeEach(() => {
16
- blackboard = new ScopedBlackboard("root");
17
- context = {
18
- blackboard,
19
- timestamp: Date.now(),
20
- deltaTime: 0,
21
- };
22
- });
23
-
24
- describe("Basic Functionality", () => {
25
- it("should execute children in order", async () => {
26
- const seq = new ReactiveSequence({ id: "seq1" });
27
- const child1 = new SuccessNode({ id: "child1" });
28
- const child2 = new SuccessNode({ id: "child2" });
29
- const child3 = new SuccessNode({ id: "child3" });
30
-
31
- seq.addChildren([child1, child2, child3]);
32
-
33
- const result = await seq.tick(context);
34
- expect(result).toBe(NodeStatus.SUCCESS);
35
- });
36
-
37
- it("should fail fast on first failure", async () => {
38
- const seq = new ReactiveSequence({ id: "seq1" });
39
- const child1 = new SuccessNode({ id: "child1" });
40
- const child2 = new FailureNode({ id: "child2" });
41
- const child3 = new SuccessNode({ id: "child3" });
42
-
43
- seq.addChildren([child1, child2, child3]);
44
-
45
- const result = await seq.tick(context);
46
- expect(result).toBe(NodeStatus.FAILURE);
47
- expect(child3.status()).toBe(NodeStatus.IDLE); // Never executed
48
- });
49
- });
50
-
51
- describe("Reactive Behavior", () => {
52
- it("should restart from beginning each tick", async () => {
53
- const seq = new ReactiveSequence({ id: "seq1" });
54
-
55
- // Track ticks for each child
56
- let child1Ticks = 0;
57
- let child2Ticks = 0;
58
-
59
- class CountingSuccess extends SuccessNode {
60
- async tick(context: TemporalContext): Promise<NodeStatus> {
61
- const superTick = super.tick.bind(this);
62
- if (this.id === "child1") child1Ticks++;
63
- if (this.id === "child2") child2Ticks++;
64
- return await superTick(context);
65
- }
66
- }
67
-
68
- const child1 = new CountingSuccess({ id: "child1" });
69
- const child2 = new CountingSuccess({ id: "child2" });
70
-
71
- // Child3 runs first time, succeeds second time
72
- let child3TickCount = 0;
73
- class TwoTickNode extends SuccessNode {
74
- async tick(context: TemporalContext): Promise<NodeStatus> {
75
- const superTick = super.tick.bind(this);
76
- child3TickCount++;
77
- if (child3TickCount === 1) {
78
- this._status = NodeStatus.RUNNING;
79
- return NodeStatus.RUNNING;
80
- }
81
- return await superTick(context);
82
- }
83
- }
84
- const child3 = new TwoTickNode({ id: "child3" });
85
-
86
- seq.addChildren([child1, child2, child3]);
87
-
88
- // First tick: child1, child2 succeed, child3 returns RUNNING
89
- let result = await seq.tick(context);
90
- expect(result).toBe(NodeStatus.RUNNING);
91
- expect(child1Ticks).toBe(1);
92
- expect(child2Ticks).toBe(1);
93
- expect(child3TickCount).toBe(1);
94
-
95
- // Second tick: should restart from child1 (reactive behavior)
96
- result = await seq.tick(context);
97
- expect(result).toBe(NodeStatus.SUCCESS);
98
- expect(child1Ticks).toBe(2); // Re-executed
99
- expect(child2Ticks).toBe(2); // Re-executed
100
- expect(child3TickCount).toBe(2);
101
- });
102
-
103
- it("should re-evaluate conditions that might change", async () => {
104
- const seq = new ReactiveSequence({ id: "seq1" });
105
-
106
- // Condition that checks blackboard value
107
- let conditionTicks = 0;
108
- class CheckValueCondition extends SuccessNode {
109
- async tick(context: TemporalContext): Promise<NodeStatus> {
110
- conditionTicks++;
111
- const value = context.blackboard.get("shouldContinue");
112
- this._status = value ? NodeStatus.SUCCESS : NodeStatus.FAILURE;
113
- return this._status;
114
- }
115
- }
116
-
117
- const condition = new CheckValueCondition({ id: "condition" });
118
-
119
- // Action that stays running
120
- let actionTicks = 0;
121
- class RunningAction extends SuccessNode {
122
- async tick(_context: TemporalContext): Promise<NodeStatus> {
123
- actionTicks++;
124
- this._status = NodeStatus.RUNNING;
125
- return NodeStatus.RUNNING;
126
- }
127
- }
128
- const action = new RunningAction({ id: "action" });
129
-
130
- seq.addChildren([condition, action]);
131
-
132
- // First tick: condition true, action runs
133
- blackboard.set("shouldContinue", true);
134
- let result = await seq.tick(context);
135
- expect(result).toBe(NodeStatus.RUNNING);
136
- expect(conditionTicks).toBe(1);
137
- expect(actionTicks).toBe(1);
138
-
139
- // Second tick: condition still true, both re-evaluated
140
- result = await seq.tick(context);
141
- expect(result).toBe(NodeStatus.RUNNING);
142
- expect(conditionTicks).toBe(2); // Condition re-checked
143
- expect(actionTicks).toBe(2);
144
-
145
- // Third tick: condition becomes false, sequence fails
146
- blackboard.set("shouldContinue", false);
147
- result = await seq.tick(context);
148
- expect(result).toBe(NodeStatus.FAILURE);
149
- expect(conditionTicks).toBe(3); // Condition re-checked again
150
- expect(actionTicks).toBe(2); // Action not ticked (condition failed)
151
- });
152
- });
153
-
154
- describe("Edge Cases", () => {
155
- it("should handle empty children array", async () => {
156
- const seq = new ReactiveSequence({ id: "seq1" });
157
- const result = await seq.tick(context);
158
- expect(result).toBe(NodeStatus.SUCCESS);
159
- });
160
-
161
- it("should handle single child", async () => {
162
- const seq = new ReactiveSequence({ id: "seq1" });
163
- const child = new SuccessNode({ id: "child1" });
164
- seq.addChild(child);
165
-
166
- const result = await seq.tick(context);
167
- expect(result).toBe(NodeStatus.SUCCESS);
168
- });
169
- });
170
- });
@@ -1,85 +0,0 @@
1
- /**
2
- * ReactiveSequence node - Restarts from beginning each tick
3
- * Responds to condition changes during execution
4
- */
5
-
6
- import { ConfigurationError } from "../errors.js";
7
- import { type TemporalContext, NodeStatus } from "../types.js";
8
- import { checkSignal } from "../utils/signal-check.js";
9
- import { Sequence } from "./sequence.js";
10
-
11
- /**
12
- * ReactiveSequence restarts from the beginning on each tick.
13
- * Unlike regular Sequence which remembers its position, ReactiveSequence
14
- * re-evaluates all children from the start, making it responsive to
15
- * conditions that might change between ticks.
16
- *
17
- * Use cases:
18
- * - Real-time monitoring where conditions might change
19
- * - Safety-critical checks that must be re-evaluated
20
- * - Guard conditions that need constant verification
21
- */
22
- export class ReactiveSequence extends Sequence {
23
- async executeTick(context: TemporalContext): Promise<NodeStatus> {
24
- this.log("Ticking (reactive - always starts from beginning)");
25
-
26
- if (this._children.length === 0) {
27
- return NodeStatus.SUCCESS;
28
- }
29
-
30
- // Always start from child 0 (reactive behavior)
31
- // Don't use currentChildIndex from parent Sequence
32
- for (let i = 0; i < this._children.length; i++) {
33
- // Check for cancellation before ticking each child
34
- checkSignal(context.signal);
35
-
36
- const child = this._children[i];
37
- if (!child) {
38
- throw new ConfigurationError(`Child at index ${i} is undefined`);
39
- }
40
-
41
- this.log(`Ticking child ${i}: ${child.name}`);
42
- const childStatus = await child.tick(context);
43
-
44
- switch (childStatus) {
45
- case NodeStatus.SUCCESS:
46
- this.log(`Child ${child.name} succeeded`);
47
- // Continue to next child
48
- break;
49
-
50
- case NodeStatus.FAILURE:
51
- this.log(`Child ${child.name} failed - sequence fails`);
52
- this._status = NodeStatus.FAILURE;
53
- return NodeStatus.FAILURE;
54
-
55
- case NodeStatus.RUNNING:
56
- this.log(`Child ${child.name} is running`);
57
- this._status = NodeStatus.RUNNING;
58
- // Return RUNNING but don't save position - will restart next tick
59
- return NodeStatus.RUNNING;
60
-
61
- default:
62
- throw new Error(`Unexpected status from child: ${childStatus}`);
63
- }
64
- }
65
-
66
- // All children succeeded
67
- this.log("All children succeeded");
68
- this._status = NodeStatus.SUCCESS;
69
- return NodeStatus.SUCCESS;
70
- }
71
-
72
- /**
73
- * Override to prevent parent Sequence from resetting currentChildIndex
74
- * (ReactiveSequence doesn't use currentChildIndex)
75
- */
76
- protected onReset(): void {
77
- // Call BaseNode reset (skip Sequence reset)
78
- this._status = NodeStatus.IDLE;
79
-
80
- // Reset all children
81
- for (const child of this._children) {
82
- child.reset();
83
- }
84
- }
85
- }
@@ -1,19 +0,0 @@
1
- /**
2
- * Recovery composite configuration schema
3
- */
4
-
5
- import { z } from "zod";
6
- import { nodeConfigurationSchema } from "../schemas/base.schema.js";
7
-
8
- /**
9
- * Schema for Recovery composite configuration
10
- * Uses base schema only - try/catch/finally logic is in child structure
11
- */
12
- export const recoveryConfigurationSchema = nodeConfigurationSchema;
13
-
14
- /**
15
- * Validated Recovery configuration type
16
- */
17
- export type ValidatedRecoveryConfiguration = z.infer<
18
- typeof recoveryConfigurationSchema
19
- >;