@framers/agentos 0.1.69 → 0.1.70

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 (128) hide show
  1. package/dist/api/agent.d.ts +98 -2
  2. package/dist/api/agent.d.ts.map +1 -1
  3. package/dist/api/agent.js +64 -9
  4. package/dist/api/agent.js.map +1 -1
  5. package/dist/api/generateImage.d.ts +109 -0
  6. package/dist/api/generateImage.d.ts.map +1 -0
  7. package/dist/api/generateImage.js +41 -0
  8. package/dist/api/generateImage.js.map +1 -0
  9. package/dist/api/generateText.d.ts +73 -3
  10. package/dist/api/generateText.d.ts.map +1 -1
  11. package/dist/api/generateText.js +29 -4
  12. package/dist/api/generateText.js.map +1 -1
  13. package/dist/api/model.d.ts +74 -4
  14. package/dist/api/model.d.ts.map +1 -1
  15. package/dist/api/model.js +79 -5
  16. package/dist/api/model.js.map +1 -1
  17. package/dist/api/streamText.d.ts +37 -1
  18. package/dist/api/streamText.d.ts.map +1 -1
  19. package/dist/api/streamText.js +188 -49
  20. package/dist/api/streamText.js.map +1 -1
  21. package/dist/api/toolAdapter.d.ts +58 -0
  22. package/dist/api/toolAdapter.d.ts.map +1 -0
  23. package/dist/api/{tool-adapter.js → toolAdapter.js} +24 -2
  24. package/dist/api/toolAdapter.js.map +1 -0
  25. package/dist/index.d.ts +5 -2
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +5 -1
  28. package/dist/index.js.map +1 -1
  29. package/dist/orchestration/builders/AgentGraph.d.ts +250 -0
  30. package/dist/orchestration/builders/AgentGraph.d.ts.map +1 -0
  31. package/dist/orchestration/builders/AgentGraph.js +338 -0
  32. package/dist/orchestration/builders/AgentGraph.js.map +1 -0
  33. package/dist/orchestration/builders/MissionBuilder.d.ts +231 -0
  34. package/dist/orchestration/builders/MissionBuilder.d.ts.map +1 -0
  35. package/dist/orchestration/builders/MissionBuilder.js +321 -0
  36. package/dist/orchestration/builders/MissionBuilder.js.map +1 -0
  37. package/dist/orchestration/builders/WorkflowBuilder.d.ts +265 -0
  38. package/dist/orchestration/builders/WorkflowBuilder.d.ts.map +1 -0
  39. package/dist/orchestration/builders/WorkflowBuilder.js +472 -0
  40. package/dist/orchestration/builders/WorkflowBuilder.js.map +1 -0
  41. package/dist/orchestration/builders/index.d.ts +7 -0
  42. package/dist/orchestration/builders/index.d.ts.map +1 -0
  43. package/dist/orchestration/builders/index.js +5 -0
  44. package/dist/orchestration/builders/index.js.map +1 -0
  45. package/dist/orchestration/builders/nodes.d.ts +36 -0
  46. package/dist/orchestration/builders/nodes.d.ts.map +1 -0
  47. package/dist/orchestration/builders/nodes.js +98 -0
  48. package/dist/orchestration/builders/nodes.js.map +1 -0
  49. package/dist/orchestration/checkpoint/ICheckpointStore.d.ts +152 -0
  50. package/dist/orchestration/checkpoint/ICheckpointStore.d.ts.map +1 -0
  51. package/dist/orchestration/checkpoint/ICheckpointStore.js +8 -0
  52. package/dist/orchestration/checkpoint/ICheckpointStore.js.map +1 -0
  53. package/dist/orchestration/checkpoint/InMemoryCheckpointStore.d.ts +89 -0
  54. package/dist/orchestration/checkpoint/InMemoryCheckpointStore.d.ts.map +1 -0
  55. package/dist/orchestration/checkpoint/InMemoryCheckpointStore.js +156 -0
  56. package/dist/orchestration/checkpoint/InMemoryCheckpointStore.js.map +1 -0
  57. package/dist/orchestration/checkpoint/index.d.ts +10 -0
  58. package/dist/orchestration/checkpoint/index.d.ts.map +1 -0
  59. package/dist/orchestration/checkpoint/index.js +10 -0
  60. package/dist/orchestration/checkpoint/index.js.map +1 -0
  61. package/dist/orchestration/compiler/GraphCompiler.d.ts +85 -0
  62. package/dist/orchestration/compiler/GraphCompiler.d.ts.map +1 -0
  63. package/dist/orchestration/compiler/GraphCompiler.js +71 -0
  64. package/dist/orchestration/compiler/GraphCompiler.js.map +1 -0
  65. package/dist/orchestration/compiler/MissionCompiler.d.ts +181 -0
  66. package/dist/orchestration/compiler/MissionCompiler.d.ts.map +1 -0
  67. package/dist/orchestration/compiler/MissionCompiler.js +219 -0
  68. package/dist/orchestration/compiler/MissionCompiler.js.map +1 -0
  69. package/dist/orchestration/compiler/SchemaLowering.d.ts +37 -0
  70. package/dist/orchestration/compiler/SchemaLowering.d.ts.map +1 -0
  71. package/dist/orchestration/compiler/SchemaLowering.js +95 -0
  72. package/dist/orchestration/compiler/SchemaLowering.js.map +1 -0
  73. package/dist/orchestration/compiler/Validator.d.ts +61 -0
  74. package/dist/orchestration/compiler/Validator.d.ts.map +1 -0
  75. package/dist/orchestration/compiler/Validator.js +96 -0
  76. package/dist/orchestration/compiler/Validator.js.map +1 -0
  77. package/dist/orchestration/compiler/index.d.ts +16 -0
  78. package/dist/orchestration/compiler/index.d.ts.map +1 -0
  79. package/dist/orchestration/compiler/index.js +13 -0
  80. package/dist/orchestration/compiler/index.js.map +1 -0
  81. package/dist/orchestration/events/GraphEvent.d.ts +233 -0
  82. package/dist/orchestration/events/GraphEvent.d.ts.map +1 -0
  83. package/dist/orchestration/events/GraphEvent.js +203 -0
  84. package/dist/orchestration/events/GraphEvent.js.map +1 -0
  85. package/dist/orchestration/events/index.d.ts +2 -0
  86. package/dist/orchestration/events/index.d.ts.map +1 -0
  87. package/dist/orchestration/events/index.js +2 -0
  88. package/dist/orchestration/events/index.js.map +1 -0
  89. package/dist/orchestration/index.d.ts +20 -0
  90. package/dist/orchestration/index.d.ts.map +1 -0
  91. package/dist/orchestration/index.js +26 -0
  92. package/dist/orchestration/index.js.map +1 -0
  93. package/dist/orchestration/ir/index.d.ts +2 -0
  94. package/dist/orchestration/ir/index.d.ts.map +1 -0
  95. package/dist/orchestration/ir/index.js +2 -0
  96. package/dist/orchestration/ir/index.js.map +1 -0
  97. package/dist/orchestration/ir/types.d.ts +540 -0
  98. package/dist/orchestration/ir/types.d.ts.map +1 -0
  99. package/dist/orchestration/ir/types.js +20 -0
  100. package/dist/orchestration/ir/types.js.map +1 -0
  101. package/dist/orchestration/runtime/GraphRuntime.d.ts +135 -0
  102. package/dist/orchestration/runtime/GraphRuntime.d.ts.map +1 -0
  103. package/dist/orchestration/runtime/GraphRuntime.js +381 -0
  104. package/dist/orchestration/runtime/GraphRuntime.js.map +1 -0
  105. package/dist/orchestration/runtime/LoopController.d.ts +173 -0
  106. package/dist/orchestration/runtime/LoopController.d.ts.map +1 -0
  107. package/dist/orchestration/runtime/LoopController.js +130 -0
  108. package/dist/orchestration/runtime/LoopController.js.map +1 -0
  109. package/dist/orchestration/runtime/NodeExecutor.d.ts +206 -0
  110. package/dist/orchestration/runtime/NodeExecutor.d.ts.map +1 -0
  111. package/dist/orchestration/runtime/NodeExecutor.js +227 -0
  112. package/dist/orchestration/runtime/NodeExecutor.js.map +1 -0
  113. package/dist/orchestration/runtime/NodeScheduler.d.ts +85 -0
  114. package/dist/orchestration/runtime/NodeScheduler.d.ts.map +1 -0
  115. package/dist/orchestration/runtime/NodeScheduler.js +180 -0
  116. package/dist/orchestration/runtime/NodeScheduler.js.map +1 -0
  117. package/dist/orchestration/runtime/StateManager.d.ts +122 -0
  118. package/dist/orchestration/runtime/StateManager.d.ts.map +1 -0
  119. package/dist/orchestration/runtime/StateManager.js +243 -0
  120. package/dist/orchestration/runtime/StateManager.js.map +1 -0
  121. package/dist/orchestration/runtime/index.d.ts +16 -0
  122. package/dist/orchestration/runtime/index.d.ts.map +1 -0
  123. package/dist/orchestration/runtime/index.js +13 -0
  124. package/dist/orchestration/runtime/index.js.map +1 -0
  125. package/package.json +10 -4
  126. package/dist/api/tool-adapter.d.ts +0 -12
  127. package/dist/api/tool-adapter.d.ts.map +0 -1
  128. package/dist/api/tool-adapter.js.map +0 -1
@@ -0,0 +1,173 @@
1
+ /**
2
+ * @file LoopController.ts
3
+ * @description Reusable, configurable ReAct (Reason + Act) loop controller for AgentOS.
4
+ *
5
+ * Extracted from the GMI implementation to provide a generic orchestration primitive
6
+ * that supports parallel/sequential tool dispatch, configurable failure modes, and
7
+ * iteration limits. Yields structured {@link LoopEvent}s for observability.
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * const controller = new LoopController();
12
+ * for await (const event of controller.execute(config, context)) {
13
+ * if (event.type === 'text_delta') process.stdout.write(event.content);
14
+ * }
15
+ * ```
16
+ */
17
+ /**
18
+ * Configuration that governs a single LoopController execution.
19
+ */
20
+ export interface LoopConfig {
21
+ /** Maximum number of ReAct iterations before the loop is forcibly terminated. */
22
+ maxIterations: number;
23
+ /**
24
+ * When `true`, all tool calls within a single iteration are dispatched in
25
+ * parallel via `Promise.allSettled`. When `false`, they execute sequentially.
26
+ */
27
+ parallelTools: boolean;
28
+ /**
29
+ * Determines how tool errors are handled:
30
+ * - `'fail_open'` — emit a `tool_error` event and continue the loop.
31
+ * - `'fail_closed'` — throw immediately, aborting the loop.
32
+ */
33
+ failureMode: 'fail_open' | 'fail_closed';
34
+ /**
35
+ * Optional per-loop timeout in milliseconds. Currently reserved for
36
+ * future implementation via AbortController; not enforced in v1.
37
+ */
38
+ timeout?: number;
39
+ }
40
+ /**
41
+ * Execution context provided to the LoopController by the caller.
42
+ * Abstracts away the underlying LLM/GMI implementation so the loop logic
43
+ * remains provider-agnostic.
44
+ */
45
+ export interface LoopContext {
46
+ /**
47
+ * Async generator that streams chunks during a single LLM inference pass.
48
+ * Must return a {@link LoopOutput} as its generator return value (the value
49
+ * passed to the final `done: true` result from `.next()`).
50
+ */
51
+ generateStream: () => AsyncGenerator<LoopChunk, LoopOutput, undefined>;
52
+ /**
53
+ * Execute a single tool call and return its result.
54
+ * Implementations should never throw — instead return a result with
55
+ * `success: false` and a populated `error` field.
56
+ */
57
+ executeTool: (toolCall: ToolCallRequest) => Promise<ToolCallResult>;
58
+ /**
59
+ * Feed tool results back into the conversation so the next `generateStream`
60
+ * call has access to them. Typically appends tool messages to the message list.
61
+ */
62
+ addToolResults: (results: ToolCallResult[]) => void;
63
+ }
64
+ /**
65
+ * A single tool invocation requested by the LLM.
66
+ */
67
+ export interface ToolCallRequest {
68
+ /** Unique identifier for this tool call within a response (matches the tool result). */
69
+ id: string;
70
+ /** Name of the tool to invoke. */
71
+ name: string;
72
+ /** Parsed arguments to pass to the tool. */
73
+ arguments: Record<string, unknown>;
74
+ }
75
+ /**
76
+ * The outcome of executing a {@link ToolCallRequest}.
77
+ */
78
+ export interface ToolCallResult {
79
+ /** Matches the originating {@link ToolCallRequest.id}. */
80
+ id: string;
81
+ /** Name of the tool that was called. */
82
+ name: string;
83
+ /** Whether the tool executed without error. */
84
+ success: boolean;
85
+ /** Serialisable output returned by the tool on success. */
86
+ output?: unknown;
87
+ /** Human-readable error message when `success` is `false`. */
88
+ error?: string;
89
+ }
90
+ /**
91
+ * A single chunk emitted by `generateStream` during inference.
92
+ * Each chunk carries either a text fragment or a set of tool call requests.
93
+ */
94
+ export interface LoopChunk {
95
+ /**
96
+ * - `'text_delta'` — incremental text from the assistant.
97
+ * - `'tool_call_request'` — the LLM has decided to call one or more tools.
98
+ */
99
+ type: 'text_delta' | 'tool_call_request';
100
+ /** Present when `type === 'text_delta'`. */
101
+ content?: string;
102
+ /** Present when `type === 'tool_call_request'`. */
103
+ toolCalls?: ToolCallRequest[];
104
+ }
105
+ /**
106
+ * The final return value of `generateStream` (carried in the generator's
107
+ * `return` slot, i.e. `{ done: true, value: LoopOutput }`).
108
+ */
109
+ export interface LoopOutput {
110
+ /** Accumulated assistant text for this iteration. */
111
+ responseText: string;
112
+ /**
113
+ * All tool calls requested in this iteration. An empty array signals that
114
+ * the LLM is done and the loop should terminate.
115
+ */
116
+ toolCalls: ToolCallRequest[];
117
+ /**
118
+ * The LLM finish reason (e.g. `'stop'`, `'tool_calls'`, `'length'`).
119
+ * Informational; not used for loop-control decisions.
120
+ */
121
+ finishReason: string;
122
+ }
123
+ /**
124
+ * Discriminated union of all events emitted by {@link LoopController.execute}.
125
+ * Consumers can switch on `event.type` to handle each case.
126
+ */
127
+ export type LoopEvent = {
128
+ type: 'text_delta';
129
+ content: string;
130
+ } | {
131
+ type: 'tool_call_request';
132
+ toolCalls: ToolCallRequest[];
133
+ } | {
134
+ type: 'tool_result';
135
+ toolName: string;
136
+ result: ToolCallResult;
137
+ } | {
138
+ type: 'tool_error';
139
+ toolName: string;
140
+ error: string;
141
+ } | {
142
+ type: 'max_iterations_reached';
143
+ iteration: number;
144
+ } | {
145
+ type: 'loop_complete';
146
+ totalIterations: number;
147
+ };
148
+ /**
149
+ * Configurable ReAct loop controller.
150
+ *
151
+ * Drives a generate → act → observe cycle, delegating LLM inference and
152
+ * tool execution to the caller-provided {@link LoopContext}. The loop
153
+ * terminates when:
154
+ *
155
+ * 1. The LLM returns no tool calls (natural stop), or
156
+ * 2. `maxIterations` is exceeded, or
157
+ * 3. A tool fails and `failureMode` is `'fail_closed'`.
158
+ *
159
+ * All intermediate events are yielded so callers can stream output to the
160
+ * user or record an audit trace.
161
+ */
162
+ export declare class LoopController {
163
+ /**
164
+ * Execute the ReAct loop and yield {@link LoopEvent}s.
165
+ *
166
+ * @param config - Loop behaviour configuration.
167
+ * @param context - Callbacks to the underlying LLM/tool layer.
168
+ * @yields {LoopEvent} Structured events for each phase of the loop.
169
+ * @throws {Error} Only when `failureMode === 'fail_closed'` and a tool fails.
170
+ */
171
+ execute(config: LoopConfig, context: LoopContext): AsyncGenerator<LoopEvent>;
172
+ }
173
+ //# sourceMappingURL=LoopController.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LoopController.d.ts","sourceRoot":"","sources":["../../../src/orchestration/runtime/LoopController.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAMH;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,iFAAiF;IACjF,aAAa,EAAE,MAAM,CAAC;IAEtB;;;OAGG;IACH,aAAa,EAAE,OAAO,CAAC;IAEvB;;;;OAIG;IACH,WAAW,EAAE,WAAW,GAAG,aAAa,CAAC;IAEzC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAMD;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B;;;;OAIG;IACH,cAAc,EAAE,MAAM,cAAc,CAAC,SAAS,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;IAEvE;;;;OAIG;IACH,WAAW,EAAE,CAAC,QAAQ,EAAE,eAAe,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;IAEpE;;;OAGG;IACH,cAAc,EAAE,CAAC,OAAO,EAAE,cAAc,EAAE,KAAK,IAAI,CAAC;CACrD;AAMD;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,wFAAwF;IACxF,EAAE,EAAE,MAAM,CAAC;IAEX,kCAAkC;IAClC,IAAI,EAAE,MAAM,CAAC;IAEb,4CAA4C;IAC5C,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,0DAA0D;IAC1D,EAAE,EAAE,MAAM,CAAC;IAEX,wCAAwC;IACxC,IAAI,EAAE,MAAM,CAAC;IAEb,+CAA+C;IAC/C,OAAO,EAAE,OAAO,CAAC;IAEjB,2DAA2D;IAC3D,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB,8DAA8D;IAC9D,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAMD;;;GAGG;AACH,MAAM,WAAW,SAAS;IACxB;;;OAGG;IACH,IAAI,EAAE,YAAY,GAAG,mBAAmB,CAAC;IAEzC,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,mDAAmD;IACnD,SAAS,CAAC,EAAE,eAAe,EAAE,CAAC;CAC/B;AAED;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,qDAAqD;IACrD,YAAY,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,SAAS,EAAE,eAAe,EAAE,CAAC;IAE7B;;;OAGG;IACH,YAAY,EAAE,MAAM,CAAC;CACtB;AAMD;;;GAGG;AACH,MAAM,MAAM,SAAS,GACjB;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACvC;IAAE,IAAI,EAAE,mBAAmB,CAAC;IAAC,SAAS,EAAE,eAAe,EAAE,CAAA;CAAE,GAC3D;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,cAAc,CAAA;CAAE,GACjE;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACvD;IAAE,IAAI,EAAE,wBAAwB,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACrD;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,eAAe,EAAE,MAAM,CAAA;CAAE,CAAC;AAMvD;;;;;;;;;;;;;GAaG;AACH,qBAAa,cAAc;IACzB;;;;;;;OAOG;IACI,OAAO,CACZ,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,WAAW,GACnB,cAAc,CAAC,SAAS,CAAC;CAuG7B"}
@@ -0,0 +1,130 @@
1
+ /**
2
+ * @file LoopController.ts
3
+ * @description Reusable, configurable ReAct (Reason + Act) loop controller for AgentOS.
4
+ *
5
+ * Extracted from the GMI implementation to provide a generic orchestration primitive
6
+ * that supports parallel/sequential tool dispatch, configurable failure modes, and
7
+ * iteration limits. Yields structured {@link LoopEvent}s for observability.
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * const controller = new LoopController();
12
+ * for await (const event of controller.execute(config, context)) {
13
+ * if (event.type === 'text_delta') process.stdout.write(event.content);
14
+ * }
15
+ * ```
16
+ */
17
+ // ---------------------------------------------------------------------------
18
+ // LoopController
19
+ // ---------------------------------------------------------------------------
20
+ /**
21
+ * Configurable ReAct loop controller.
22
+ *
23
+ * Drives a generate → act → observe cycle, delegating LLM inference and
24
+ * tool execution to the caller-provided {@link LoopContext}. The loop
25
+ * terminates when:
26
+ *
27
+ * 1. The LLM returns no tool calls (natural stop), or
28
+ * 2. `maxIterations` is exceeded, or
29
+ * 3. A tool fails and `failureMode` is `'fail_closed'`.
30
+ *
31
+ * All intermediate events are yielded so callers can stream output to the
32
+ * user or record an audit trace.
33
+ */
34
+ export class LoopController {
35
+ /**
36
+ * Execute the ReAct loop and yield {@link LoopEvent}s.
37
+ *
38
+ * @param config - Loop behaviour configuration.
39
+ * @param context - Callbacks to the underlying LLM/tool layer.
40
+ * @yields {LoopEvent} Structured events for each phase of the loop.
41
+ * @throws {Error} Only when `failureMode === 'fail_closed'` and a tool fails.
42
+ */
43
+ async *execute(config, context) {
44
+ let iteration = 0;
45
+ while (iteration < config.maxIterations) {
46
+ iteration++;
47
+ // ------------------------------------------------------------------
48
+ // Generate phase: consume the streaming generator chunk by chunk,
49
+ // yielding events as they arrive. The final LoopOutput is captured
50
+ // from the generator's return value (done === true).
51
+ // ------------------------------------------------------------------
52
+ const gen = context.generateStream();
53
+ let gmiOutput;
54
+ while (true) {
55
+ const { value, done } = await gen.next();
56
+ if (done) {
57
+ // The generator's return value is the LoopOutput summary.
58
+ gmiOutput = value;
59
+ break;
60
+ }
61
+ // Yield chunk events to the caller.
62
+ const chunk = value;
63
+ if (chunk.type === 'text_delta' && chunk.content) {
64
+ yield { type: 'text_delta', content: chunk.content };
65
+ }
66
+ if (chunk.type === 'tool_call_request' && chunk.toolCalls) {
67
+ yield { type: 'tool_call_request', toolCalls: chunk.toolCalls };
68
+ }
69
+ }
70
+ // Natural termination: no tool calls requested.
71
+ if (!gmiOutput || gmiOutput.toolCalls.length === 0) {
72
+ yield { type: 'loop_complete', totalIterations: iteration };
73
+ return;
74
+ }
75
+ // ------------------------------------------------------------------
76
+ // Act phase: execute tool calls (parallel or sequential).
77
+ // ------------------------------------------------------------------
78
+ const toolCalls = gmiOutput.toolCalls;
79
+ let results;
80
+ if (config.parallelTools) {
81
+ // Dispatch all tool calls simultaneously; collect all outcomes even
82
+ // if some reject, so we can still feed partial results back.
83
+ const settled = await Promise.allSettled(toolCalls.map((tc) => context.executeTool(tc)));
84
+ results = settled.map((s, i) => {
85
+ if (s.status === 'fulfilled')
86
+ return s.value;
87
+ // Convert a rejected promise into a failed ToolCallResult so
88
+ // downstream handling is uniform.
89
+ return {
90
+ id: toolCalls[i].id,
91
+ name: toolCalls[i].name,
92
+ success: false,
93
+ error: String(s.reason),
94
+ };
95
+ });
96
+ }
97
+ else {
98
+ // Sequential execution — preserves order and stops early on
99
+ // fail_closed errors (handled in the yield loop below).
100
+ results = [];
101
+ for (const tc of toolCalls) {
102
+ const result = await context.executeTool(tc);
103
+ results.push(result);
104
+ }
105
+ }
106
+ // ------------------------------------------------------------------
107
+ // Observe phase: yield results, handle failures per failureMode.
108
+ // ------------------------------------------------------------------
109
+ for (const result of results) {
110
+ if (result.success) {
111
+ yield { type: 'tool_result', toolName: result.name, result };
112
+ }
113
+ else {
114
+ const errorMsg = result.error ?? 'unknown error';
115
+ yield { type: 'tool_error', toolName: result.name, error: errorMsg };
116
+ if (config.failureMode === 'fail_closed') {
117
+ throw new Error(`Tool ${result.name} failed (fail_closed): ${errorMsg}`);
118
+ }
119
+ // fail_open: continue — the error is already yielded above.
120
+ }
121
+ }
122
+ // Feed all results (successes and failures) back into the conversation
123
+ // so the LLM has full context on the next iteration.
124
+ context.addToolResults(results);
125
+ }
126
+ // Exceeded maxIterations without a natural stop.
127
+ yield { type: 'max_iterations_reached', iteration: config.maxIterations };
128
+ }
129
+ }
130
+ //# sourceMappingURL=LoopController.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LoopController.js","sourceRoot":"","sources":["../../../src/orchestration/runtime/LoopController.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,206 @@
1
+ /**
2
+ * @file NodeExecutor.ts
3
+ * @description Dispatches execution to the appropriate handler based on `GraphNode.executorConfig.type`.
4
+ *
5
+ * The executor is intentionally thin — it contains no retry logic (handled by `GraphRuntime`),
6
+ * no state mutation (handled by `StateManager`), and no event emission (handled by the caller).
7
+ * Each private method maps one-to-one with a `NodeExecutorConfig` variant.
8
+ *
9
+ * Execution flow:
10
+ * `execute()` → optional timeout race → `executeNode()` → variant handler
11
+ *
12
+ * Placeholders for `gmi`, `extension`, and `subgraph` nodes are wired in `GraphRuntime`
13
+ * after the `LoopController` and extension managers are available.
14
+ */
15
+ import type { GraphNode, GraphState } from '../ir/types.js';
16
+ import type { GraphEvent } from '../events/GraphEvent.js';
17
+ /**
18
+ * The normalised result returned by every `NodeExecutor.execute()` call regardless
19
+ * of which executor variant was dispatched.
20
+ *
21
+ * The runtime inspects these fields to decide the next graph step:
22
+ * - `success` — whether the node completed without error.
23
+ * - `output` — arbitrary payload produced by the node (tool result, LLM response, etc.).
24
+ * - `error` — human-readable error message; only present when `success` is `false`.
25
+ * - `routeTarget` — next node id determined by a `router` or `guardrail` node.
26
+ * - `scratchUpdate` — partial object merged into `GraphState.scratch` by `StateManager`.
27
+ * - `artifactsUpdate` — partial object merged into `GraphState.artifacts` by `StateManager`.
28
+ * - `events` — additional `GraphEvent` values the executor wants the runtime to emit.
29
+ * - `interrupt` — when `true`, the runtime suspends the run and waits for human input.
30
+ */
31
+ export interface NodeExecutionResult {
32
+ /** Whether the node completed successfully. */
33
+ success: boolean;
34
+ /** Arbitrary output produced by the node. */
35
+ output?: unknown;
36
+ /** Human-readable error description; populated only when `success` is `false`. */
37
+ error?: string;
38
+ /** Target node id returned by `router` or guardrail rerouting. */
39
+ routeTarget?: string;
40
+ /** Partial update to merge into `GraphState.scratch`. */
41
+ scratchUpdate?: Record<string, unknown>;
42
+ /** Partial update to merge into `GraphState.artifacts`. */
43
+ artifactsUpdate?: Record<string, unknown>;
44
+ /** Extra runtime events the executor wants to surface to callers. */
45
+ events?: GraphEvent[];
46
+ /** When `true`, the runtime must suspend and await human resolution. */
47
+ interrupt?: boolean;
48
+ }
49
+ /**
50
+ * External dependencies injected into `NodeExecutor` at construction time.
51
+ *
52
+ * Using an interface rather than concrete types keeps the executor decoupled from
53
+ * the full `ToolOrchestrator` and `GuardrailEngine` implementations and makes the
54
+ * unit-test surface minimal.
55
+ *
56
+ * GMI / extension / subgraph managers are omitted here and wired by `GraphRuntime`
57
+ * once those subsystems are available.
58
+ */
59
+ export interface NodeExecutorDeps {
60
+ /**
61
+ * Routes tool-call requests to registered `ITool` implementations.
62
+ * When absent, any `tool` node will resolve with `success: false`.
63
+ */
64
+ toolOrchestrator?: {
65
+ /**
66
+ * Process a single tool call and return its result.
67
+ *
68
+ * @param details - Wrapper containing `toolCallRequest.toolName` and `toolCallRequest.arguments`.
69
+ * @returns Promise resolving to an object with at least `output` and `isError` / `success`.
70
+ */
71
+ processToolCall(details: {
72
+ toolCallRequest: {
73
+ toolName: string;
74
+ arguments: Record<string, unknown>;
75
+ };
76
+ }): Promise<{
77
+ success?: boolean;
78
+ isError?: boolean;
79
+ output?: unknown;
80
+ error?: string;
81
+ }>;
82
+ };
83
+ /**
84
+ * Evaluates one or more named guardrails against a content payload.
85
+ * When absent, guardrail nodes are treated as always-passing.
86
+ */
87
+ guardrailEngine?: {
88
+ /**
89
+ * Run all listed guardrails against `content` and return a combined verdict.
90
+ *
91
+ * @param content - The payload to evaluate (typically `GraphState.scratch`).
92
+ * @param guardrailIds - Ordered list of guardrail identifiers to run.
93
+ * @returns Aggregated result with `passed` flag and per-guardrail `results`.
94
+ */
95
+ evaluate(content: unknown, guardrailIds: string[]): Promise<{
96
+ passed: boolean;
97
+ results: unknown[];
98
+ }>;
99
+ };
100
+ }
101
+ /**
102
+ * Stateless executor that dispatches a `GraphNode` to the appropriate handler.
103
+ *
104
+ * One `NodeExecutor` instance is typically shared across the lifetime of a `GraphRuntime`
105
+ * and reused for every node invocation within every run. All state is passed through
106
+ * `GraphState` and returned via `NodeExecutionResult`.
107
+ *
108
+ * @example
109
+ * ```ts
110
+ * const executor = new NodeExecutor({ toolOrchestrator, guardrailEngine });
111
+ * const result = await executor.execute(node, graphState);
112
+ * if (!result.success) console.error(result.error);
113
+ * ```
114
+ */
115
+ export declare class NodeExecutor {
116
+ private readonly deps;
117
+ /**
118
+ * @param deps - External service adapters. All fields are optional; missing services
119
+ * cause graceful degradation rather than hard failures.
120
+ */
121
+ constructor(deps: NodeExecutorDeps);
122
+ /**
123
+ * Execute `node` against the provided `state`, optionally racing against a timeout.
124
+ *
125
+ * If `node.timeout` is set, execution races against a timer that resolves with a
126
+ * `success: false` result after the specified number of milliseconds.
127
+ *
128
+ * @param node - Immutable node descriptor from the compiled graph IR.
129
+ * @param state - Current (partial) graph state threaded from the runtime.
130
+ * @returns A `NodeExecutionResult` describing the outcome.
131
+ */
132
+ execute(node: GraphNode, state: Partial<GraphState>): Promise<NodeExecutionResult>;
133
+ /**
134
+ * Dispatches to the correct private handler based on `executorConfig.type`.
135
+ *
136
+ * Each branch receives only the narrowed config type it needs, keeping handler
137
+ * signatures precise and avoiding accidental access to unrelated fields.
138
+ */
139
+ private executeNode;
140
+ /**
141
+ * Invokes a registered `ITool` via `ToolOrchestrator.processToolCall()`.
142
+ *
143
+ * Static args from `config.args` are merged into the call. The orchestrator
144
+ * is responsible for argument validation and schema enforcement.
145
+ *
146
+ * @param config - `{ type: 'tool'; toolName: string; args?: Record<string, unknown> }`
147
+ * @param state - Current graph state (not used directly but available for future extension).
148
+ */
149
+ private executeTool;
150
+ /**
151
+ * Evaluates a `GraphCondition` and returns the resolved target node id as `routeTarget`.
152
+ *
153
+ * Two condition strategies are supported:
154
+ * - `function` — calls the runtime-registered TypeScript `fn` directly.
155
+ * - `expression` — delegates to `evaluateExpression()` for DSL string evaluation.
156
+ *
157
+ * @param config - `{ type: 'router'; condition: GraphCondition }`
158
+ * @param state - Current graph state passed to the condition function/evaluator.
159
+ */
160
+ private executeRouter;
161
+ /**
162
+ * Evaluates a set of guardrails against `state.scratch` and either passes through
163
+ * or triggers the configured violation action.
164
+ *
165
+ * When no `guardrailEngine` is configured, the node always passes (permissive default).
166
+ * Violation handling currently supports `'reroute'`; `'block'`, `'warn'`, and `'sanitize'`
167
+ * are propagated via `success: false` for the runtime to handle.
168
+ *
169
+ * @param config - Guardrail node config with `guardrailIds`, `onViolation`, and optional `rerouteTarget`.
170
+ * @param state - Current graph state; `state.scratch` is passed to the engine as the content payload.
171
+ */
172
+ private executeGuardrail;
173
+ /**
174
+ * Suspends execution and surfaces a prompt to a human operator.
175
+ *
176
+ * The runtime must treat `interrupt: true` as a signal to persist state, emit an
177
+ * `interrupt` event, and halt the current run until the operator provides a response.
178
+ *
179
+ * @param config - `{ type: 'human'; prompt: string }`
180
+ */
181
+ private executeHuman;
182
+ /**
183
+ * Minimal DSL expression evaluator for `{ type: 'expression' }` routing conditions.
184
+ *
185
+ * Current implementation is a stub that returns the expression string unchanged.
186
+ * A full implementation would parse `"scratch.confidence > 0.8 ? 'approve' : 'review'"`
187
+ * using a sandboxed interpreter with dot-path access to `state` fields.
188
+ *
189
+ * @param expr - The DSL expression string from `GraphConditionExpr`.
190
+ * @param state - Current graph state (available for a real implementation to traverse).
191
+ * @returns The resolved target node id (or the raw expression until the evaluator is complete).
192
+ *
193
+ * @todo Implement a sandboxed expression interpreter (tracked separately).
194
+ */
195
+ private evaluateExpression;
196
+ /**
197
+ * Builds a `Promise` that resolves with a timeout-failure result after `ms` milliseconds.
198
+ *
199
+ * Races against `executeNode()` inside `execute()` to enforce `GraphNode.timeout`.
200
+ *
201
+ * @param ms - Timeout duration in milliseconds.
202
+ * @param nodeId - Node id included in the error message for debugging.
203
+ */
204
+ private buildTimeoutPromise;
205
+ }
206
+ //# sourceMappingURL=NodeExecutor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NodeExecutor.d.ts","sourceRoot":"","sources":["../../../src/orchestration/runtime/NodeExecutor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAkB,MAAM,gBAAgB,CAAC;AAC5E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAM1D;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,mBAAmB;IAClC,+CAA+C;IAC/C,OAAO,EAAE,OAAO,CAAC;IACjB,6CAA6C;IAC7C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,kFAAkF;IAClF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yDAAyD;IACzD,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,2DAA2D;IAC3D,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC1C,qEAAqE;IACrE,MAAM,CAAC,EAAE,UAAU,EAAE,CAAC;IACtB,wEAAwE;IACxE,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAMD;;;;;;;;;GASG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,gBAAgB,CAAC,EAAE;QACjB;;;;;WAKG;QACH,eAAe,CAAC,OAAO,EAAE;YACvB,eAAe,EAAE;gBAAE,QAAQ,EAAE,MAAM,CAAC;gBAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;aAAE,CAAC;SAC3E,GAAG,OAAO,CAAC;YAAE,OAAO,CAAC,EAAE,OAAO,CAAC;YAAC,OAAO,CAAC,EAAE,OAAO,CAAC;YAAC,MAAM,CAAC,EAAE,OAAO,CAAC;YAAC,KAAK,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KACzF,CAAC;IAEF;;;OAGG;IACH,eAAe,CAAC,EAAE;QAChB;;;;;;WAMG;QACH,QAAQ,CACN,OAAO,EAAE,OAAO,EAChB,YAAY,EAAE,MAAM,EAAE,GACrB,OAAO,CAAC;YAAE,MAAM,EAAE,OAAO,CAAC;YAAC,OAAO,EAAE,OAAO,EAAE,CAAA;SAAE,CAAC,CAAC;KACrD,CAAC;CACH;AAMD;;;;;;;;;;;;;GAaG;AACH,qBAAa,YAAY;IAKX,OAAO,CAAC,QAAQ,CAAC,IAAI;IAJjC;;;OAGG;gBAC0B,IAAI,EAAE,gBAAgB;IAMnD;;;;;;;;;OASG;IACG,OAAO,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAcxF;;;;;OAKG;YACW,WAAW;IAsCzB;;;;;;;;OAQG;YACW,WAAW;IAyBzB;;;;;;;;;OASG;YACW,aAAa;IAiB3B;;;;;;;;;;OAUG;YACW,gBAAgB;IAgC9B;;;;;;;OAOG;IACH,OAAO,CAAC,YAAY;IAepB;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,kBAAkB;IAI1B;;;;;;;OAOG;IACH,OAAO,CAAC,mBAAmB;CAQ5B"}