@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,227 @@
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
+ // ---------------------------------------------------------------------------
16
+ // NodeExecutor
17
+ // ---------------------------------------------------------------------------
18
+ /**
19
+ * Stateless executor that dispatches a `GraphNode` to the appropriate handler.
20
+ *
21
+ * One `NodeExecutor` instance is typically shared across the lifetime of a `GraphRuntime`
22
+ * and reused for every node invocation within every run. All state is passed through
23
+ * `GraphState` and returned via `NodeExecutionResult`.
24
+ *
25
+ * @example
26
+ * ```ts
27
+ * const executor = new NodeExecutor({ toolOrchestrator, guardrailEngine });
28
+ * const result = await executor.execute(node, graphState);
29
+ * if (!result.success) console.error(result.error);
30
+ * ```
31
+ */
32
+ export class NodeExecutor {
33
+ /**
34
+ * @param deps - External service adapters. All fields are optional; missing services
35
+ * cause graceful degradation rather than hard failures.
36
+ */
37
+ constructor(deps) {
38
+ this.deps = deps;
39
+ }
40
+ // ---------------------------------------------------------------------------
41
+ // Public API
42
+ // ---------------------------------------------------------------------------
43
+ /**
44
+ * Execute `node` against the provided `state`, optionally racing against a timeout.
45
+ *
46
+ * If `node.timeout` is set, execution races against a timer that resolves with a
47
+ * `success: false` result after the specified number of milliseconds.
48
+ *
49
+ * @param node - Immutable node descriptor from the compiled graph IR.
50
+ * @param state - Current (partial) graph state threaded from the runtime.
51
+ * @returns A `NodeExecutionResult` describing the outcome.
52
+ */
53
+ async execute(node, state) {
54
+ if (node.timeout) {
55
+ return Promise.race([
56
+ this.executeNode(node, state),
57
+ this.buildTimeoutPromise(node.timeout, node.id),
58
+ ]);
59
+ }
60
+ return this.executeNode(node, state);
61
+ }
62
+ // ---------------------------------------------------------------------------
63
+ // Internal dispatch
64
+ // ---------------------------------------------------------------------------
65
+ /**
66
+ * Dispatches to the correct private handler based on `executorConfig.type`.
67
+ *
68
+ * Each branch receives only the narrowed config type it needs, keeping handler
69
+ * signatures precise and avoiding accidental access to unrelated fields.
70
+ */
71
+ async executeNode(node, state) {
72
+ const config = node.executorConfig;
73
+ switch (config.type) {
74
+ case 'tool':
75
+ return this.executeTool(config, state);
76
+ case 'router':
77
+ return this.executeRouter(config, state);
78
+ case 'guardrail':
79
+ return this.executeGuardrail(config, state);
80
+ case 'human':
81
+ return this.executeHuman(config);
82
+ case 'gmi':
83
+ // GMI execution is delegated to `LoopController` and wired in `GraphRuntime`.
84
+ // This placeholder allows the executor to be used before the LLM subsystem is ready.
85
+ return { success: true, output: 'gmi-placeholder' };
86
+ case 'extension':
87
+ // Extension execution is wired by `GraphRuntime` once the extension manager is available.
88
+ return { success: true, output: 'extension-placeholder' };
89
+ case 'subgraph':
90
+ // Subgraph delegation is wired by `GraphRuntime` once nested graph lookup is available.
91
+ return { success: true, output: 'subgraph-placeholder' };
92
+ }
93
+ }
94
+ // ---------------------------------------------------------------------------
95
+ // Variant handlers
96
+ // ---------------------------------------------------------------------------
97
+ /**
98
+ * Invokes a registered `ITool` via `ToolOrchestrator.processToolCall()`.
99
+ *
100
+ * Static args from `config.args` are merged into the call. The orchestrator
101
+ * is responsible for argument validation and schema enforcement.
102
+ *
103
+ * @param config - `{ type: 'tool'; toolName: string; args?: Record<string, unknown> }`
104
+ * @param state - Current graph state (not used directly but available for future extension).
105
+ */
106
+ async executeTool(config, _state) {
107
+ if (!this.deps.toolOrchestrator) {
108
+ return {
109
+ success: false,
110
+ error: 'No ToolOrchestrator configured',
111
+ };
112
+ }
113
+ const result = await this.deps.toolOrchestrator.processToolCall({
114
+ toolCallRequest: {
115
+ toolName: config.toolName,
116
+ arguments: config.args ?? {},
117
+ },
118
+ });
119
+ return {
120
+ success: result.success ?? !result.isError,
121
+ output: result.output,
122
+ error: result.error,
123
+ };
124
+ }
125
+ /**
126
+ * Evaluates a `GraphCondition` and returns the resolved target node id as `routeTarget`.
127
+ *
128
+ * Two condition strategies are supported:
129
+ * - `function` — calls the runtime-registered TypeScript `fn` directly.
130
+ * - `expression` — delegates to `evaluateExpression()` for DSL string evaluation.
131
+ *
132
+ * @param config - `{ type: 'router'; condition: GraphCondition }`
133
+ * @param state - Current graph state passed to the condition function/evaluator.
134
+ */
135
+ async executeRouter(config, state) {
136
+ let target;
137
+ if (config.condition.type === 'function') {
138
+ // The function condition receives the full state and returns a node id.
139
+ target = config.condition.fn(state);
140
+ }
141
+ else {
142
+ // Expression-based conditions are evaluated by the minimal DSL interpreter.
143
+ target = this.evaluateExpression(config.condition.expr, state);
144
+ }
145
+ return { success: true, routeTarget: target };
146
+ }
147
+ /**
148
+ * Evaluates a set of guardrails against `state.scratch` and either passes through
149
+ * or triggers the configured violation action.
150
+ *
151
+ * When no `guardrailEngine` is configured, the node always passes (permissive default).
152
+ * Violation handling currently supports `'reroute'`; `'block'`, `'warn'`, and `'sanitize'`
153
+ * are propagated via `success: false` for the runtime to handle.
154
+ *
155
+ * @param config - Guardrail node config with `guardrailIds`, `onViolation`, and optional `rerouteTarget`.
156
+ * @param state - Current graph state; `state.scratch` is passed to the engine as the content payload.
157
+ */
158
+ async executeGuardrail(config, state) {
159
+ if (!this.deps.guardrailEngine) {
160
+ // Permissive fallback: no engine means no enforcement.
161
+ return {
162
+ success: true,
163
+ output: { passed: true, message: 'No guardrail engine configured' },
164
+ };
165
+ }
166
+ const result = await this.deps.guardrailEngine.evaluate(state.scratch, config.guardrailIds);
167
+ if (!result.passed && config.onViolation === 'reroute' && config.rerouteTarget) {
168
+ // Soft violation: redirect the graph to the recovery branch.
169
+ return { success: true, routeTarget: config.rerouteTarget };
170
+ }
171
+ // For all other violation actions (block, warn, sanitize) the runtime inspects
172
+ // `success: false` and acts according to its own policy.
173
+ return {
174
+ success: result.passed,
175
+ output: result,
176
+ };
177
+ }
178
+ /**
179
+ * Suspends execution and surfaces a prompt to a human operator.
180
+ *
181
+ * The runtime must treat `interrupt: true` as a signal to persist state, emit an
182
+ * `interrupt` event, and halt the current run until the operator provides a response.
183
+ *
184
+ * @param config - `{ type: 'human'; prompt: string }`
185
+ */
186
+ executeHuman(config) {
187
+ return Promise.resolve({
188
+ success: false,
189
+ interrupt: true,
190
+ error: 'Awaiting human input',
191
+ output: { prompt: config.prompt },
192
+ });
193
+ }
194
+ // ---------------------------------------------------------------------------
195
+ // Utilities
196
+ // ---------------------------------------------------------------------------
197
+ /**
198
+ * Minimal DSL expression evaluator for `{ type: 'expression' }` routing conditions.
199
+ *
200
+ * Current implementation is a stub that returns the expression string unchanged.
201
+ * A full implementation would parse `"scratch.confidence > 0.8 ? 'approve' : 'review'"`
202
+ * using a sandboxed interpreter with dot-path access to `state` fields.
203
+ *
204
+ * @param expr - The DSL expression string from `GraphConditionExpr`.
205
+ * @param state - Current graph state (available for a real implementation to traverse).
206
+ * @returns The resolved target node id (or the raw expression until the evaluator is complete).
207
+ *
208
+ * @todo Implement a sandboxed expression interpreter (tracked separately).
209
+ */
210
+ evaluateExpression(expr, _state) {
211
+ return expr;
212
+ }
213
+ /**
214
+ * Builds a `Promise` that resolves with a timeout-failure result after `ms` milliseconds.
215
+ *
216
+ * Races against `executeNode()` inside `execute()` to enforce `GraphNode.timeout`.
217
+ *
218
+ * @param ms - Timeout duration in milliseconds.
219
+ * @param nodeId - Node id included in the error message for debugging.
220
+ */
221
+ buildTimeoutPromise(ms, nodeId) {
222
+ return new Promise((resolve) => {
223
+ setTimeout(() => resolve({ success: false, error: `Node ${nodeId} timeout after ${ms}ms` }), ms);
224
+ });
225
+ }
226
+ }
227
+ //# sourceMappingURL=NodeExecutor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NodeExecutor.js","sourceRoot":"","sources":["../../../src/orchestration/runtime/NodeExecutor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * @file NodeScheduler.ts
3
+ * @description Topological ordering, cycle detection, and ready-node detection
4
+ * for compiled execution graph scheduling in the AgentOS Unified Orchestration Layer.
5
+ *
6
+ * Uses Kahn's algorithm (BFS-based) for topological sorting, which also serves
7
+ * as the foundation for cycle detection. The scheduler treats START and END as
8
+ * virtual nodes that participate in edge traversal but are excluded from the
9
+ * returned topological order.
10
+ */
11
+ import type { GraphNode, GraphEdge } from '../ir/types.js';
12
+ /**
13
+ * Schedules graph node execution by computing topological ordering, detecting
14
+ * structural issues (cycles, unreachable nodes), and determining which nodes
15
+ * are ready to run given a set of already-completed nodes.
16
+ *
17
+ * All methods are pure and stateless with respect to execution — the scheduler
18
+ * only reads the static graph structure provided at construction time.
19
+ */
20
+ export declare class NodeScheduler {
21
+ /** Maps each node id to its outgoing neighbour ids. Includes START and END. */
22
+ private adjacency;
23
+ /** Maps each node id to the ids of nodes that have edges pointing into it. Includes START and END. */
24
+ private predecessors;
25
+ /** Set of real (non-sentinel) node ids derived from the provided GraphNode array. */
26
+ private nodeIds;
27
+ /**
28
+ * Constructs a NodeScheduler from a compiled graph's node and edge lists.
29
+ *
30
+ * @param nodes - All real (non-sentinel) graph nodes.
31
+ * @param edges - All directed edges, including those from/to START or END sentinels.
32
+ */
33
+ constructor(nodes: GraphNode[], edges: GraphEdge[]);
34
+ /**
35
+ * Returns real node ids in a valid topological execution order using Kahn's
36
+ * algorithm (BFS over in-degree).
37
+ *
38
+ * START and END sentinels are intentionally excluded from the returned array
39
+ * because they are virtual control-flow markers, not executable nodes.
40
+ *
41
+ * If the graph contains a cycle, the returned array will be shorter than
42
+ * `nodeIds.size` — use {@link hasCycles} to distinguish this case explicitly.
43
+ *
44
+ * @returns Ordered array of real node ids; empty if there are no real nodes.
45
+ */
46
+ topologicalSort(): string[];
47
+ /**
48
+ * Returns `true` if the graph contains at least one directed cycle among the
49
+ * real nodes (sentinels are excluded from cycle detection).
50
+ *
51
+ * Implemented by comparing the length of the topological sort result against
52
+ * the total number of real nodes: Kahn's algorithm processes every node in a
53
+ * DAG, so any shortfall indicates nodes trapped inside a cycle.
54
+ *
55
+ * @returns `true` when a cycle exists; `false` for a valid DAG.
56
+ */
57
+ hasCycles(): boolean;
58
+ /**
59
+ * Returns the ids of all real nodes that are eligible to execute next, given
60
+ * the set of nodes that have already finished (completed or skipped).
61
+ *
62
+ * A node is "ready" when:
63
+ * 1. It has not already completed or been skipped.
64
+ * 2. Every one of its predecessors is either the START sentinel or a member of
65
+ * the completed/skipped set.
66
+ *
67
+ * @param completedNodeIds - Node ids that have successfully finished execution.
68
+ * @param skippedNodeIds - Node ids that were bypassed (e.g. via conditional routing).
69
+ * @returns Array of node ids that can be dispatched for execution immediately.
70
+ */
71
+ getReadyNodes(completedNodeIds: string[], skippedNodeIds?: string[]): string[];
72
+ /**
73
+ * Returns the ids of all real nodes that are not reachable from the START
74
+ * sentinel via a BFS traversal of the adjacency list.
75
+ *
76
+ * Unreachable (orphan) nodes indicate a structural authoring error: they can
77
+ * never execute because no execution path leads to them. The runtime may
78
+ * choose to warn, error, or prune these nodes before starting a run.
79
+ *
80
+ * @returns Array of node ids that cannot be reached from START; empty for a
81
+ * well-formed graph.
82
+ */
83
+ getUnreachableNodes(): string[];
84
+ }
85
+ //# sourceMappingURL=NodeScheduler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NodeScheduler.d.ts","sourceRoot":"","sources":["../../../src/orchestration/runtime/NodeScheduler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAG3D;;;;;;;GAOG;AACH,qBAAa,aAAa;IACxB,+EAA+E;IAC/E,OAAO,CAAC,SAAS,CAAoC;IAErD,sGAAsG;IACtG,OAAO,CAAC,YAAY,CAAoC;IAExD,qFAAqF;IACrF,OAAO,CAAC,OAAO,CAAc;IAE7B;;;;;OAKG;gBACS,KAAK,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE;IAoBlD;;;;;;;;;;;OAWG;IACH,eAAe,IAAI,MAAM,EAAE;IAwD3B;;;;;;;;;OASG;IACH,SAAS,IAAI,OAAO;IAQpB;;;;;;;;;;;;OAYG;IACH,aAAa,CAAC,gBAAgB,EAAE,MAAM,EAAE,EAAE,cAAc,GAAE,MAAM,EAAO,GAAG,MAAM,EAAE;IAuBlF;;;;;;;;;;OAUG;IACH,mBAAmB,IAAI,MAAM,EAAE;CAmBhC"}
@@ -0,0 +1,180 @@
1
+ /**
2
+ * @file NodeScheduler.ts
3
+ * @description Topological ordering, cycle detection, and ready-node detection
4
+ * for compiled execution graph scheduling in the AgentOS Unified Orchestration Layer.
5
+ *
6
+ * Uses Kahn's algorithm (BFS-based) for topological sorting, which also serves
7
+ * as the foundation for cycle detection. The scheduler treats START and END as
8
+ * virtual nodes that participate in edge traversal but are excluded from the
9
+ * returned topological order.
10
+ */
11
+ import { START, END } from '../ir/types.js';
12
+ /**
13
+ * Schedules graph node execution by computing topological ordering, detecting
14
+ * structural issues (cycles, unreachable nodes), and determining which nodes
15
+ * are ready to run given a set of already-completed nodes.
16
+ *
17
+ * All methods are pure and stateless with respect to execution — the scheduler
18
+ * only reads the static graph structure provided at construction time.
19
+ */
20
+ export class NodeScheduler {
21
+ /**
22
+ * Constructs a NodeScheduler from a compiled graph's node and edge lists.
23
+ *
24
+ * @param nodes - All real (non-sentinel) graph nodes.
25
+ * @param edges - All directed edges, including those from/to START or END sentinels.
26
+ */
27
+ constructor(nodes, edges) {
28
+ /** Maps each node id to its outgoing neighbour ids. Includes START and END. */
29
+ this.adjacency = new Map();
30
+ /** Maps each node id to the ids of nodes that have edges pointing into it. Includes START and END. */
31
+ this.predecessors = new Map();
32
+ this.nodeIds = new Set(nodes.map(n => n.id));
33
+ // Initialise adjacency and predecessor lists for every real node plus the
34
+ // two virtual sentinels so edge lookups never need a null-check.
35
+ for (const id of [START, END, ...this.nodeIds]) {
36
+ this.adjacency.set(id, []);
37
+ this.predecessors.set(id, []);
38
+ }
39
+ for (const edge of edges) {
40
+ this.adjacency.get(edge.source)?.push(edge.target);
41
+ this.predecessors.get(edge.target)?.push(edge.source);
42
+ }
43
+ }
44
+ // ---------------------------------------------------------------------------
45
+ // Topological ordering
46
+ // ---------------------------------------------------------------------------
47
+ /**
48
+ * Returns real node ids in a valid topological execution order using Kahn's
49
+ * algorithm (BFS over in-degree).
50
+ *
51
+ * START and END sentinels are intentionally excluded from the returned array
52
+ * because they are virtual control-flow markers, not executable nodes.
53
+ *
54
+ * If the graph contains a cycle, the returned array will be shorter than
55
+ * `nodeIds.size` — use {@link hasCycles} to distinguish this case explicitly.
56
+ *
57
+ * @returns Ordered array of real node ids; empty if there are no real nodes.
58
+ */
59
+ topologicalSort() {
60
+ // Compute in-degree for every real node (edges from sentinels count too).
61
+ const inDegree = new Map();
62
+ for (const id of this.nodeIds) {
63
+ const preds = this.predecessors.get(id) ?? [];
64
+ inDegree.set(id, preds.length);
65
+ }
66
+ // Seed the queue with nodes that have no predecessors at all, or whose
67
+ // only predecessors are START (treated as "already satisfied" at t=0).
68
+ const queue = [];
69
+ for (const [id, degree] of inDegree) {
70
+ // A node is initially ready when all its predecessors are sentinels
71
+ // (START/END) or it has no predecessors.
72
+ const realPredCount = (this.predecessors.get(id) ?? []).filter(p => p !== START && p !== END).length;
73
+ if (realPredCount === 0) {
74
+ queue.push(id);
75
+ }
76
+ }
77
+ const sorted = [];
78
+ // Track a "virtual" in-degree that only counts real predecessors so that
79
+ // START/END sentinel edges don't artificially inflate the degree.
80
+ const realInDegree = new Map();
81
+ for (const id of this.nodeIds) {
82
+ realInDegree.set(id, (this.predecessors.get(id) ?? []).filter(p => p !== START && p !== END).length);
83
+ }
84
+ while (queue.length > 0) {
85
+ const current = queue.shift();
86
+ sorted.push(current);
87
+ for (const neighbour of this.adjacency.get(current) ?? []) {
88
+ // Skip sentinel targets — they have no real in-degree entry.
89
+ if (!this.nodeIds.has(neighbour))
90
+ continue;
91
+ const remaining = (realInDegree.get(neighbour) ?? 0) - 1;
92
+ realInDegree.set(neighbour, remaining);
93
+ if (remaining === 0) {
94
+ queue.push(neighbour);
95
+ }
96
+ }
97
+ }
98
+ return sorted;
99
+ }
100
+ // ---------------------------------------------------------------------------
101
+ // Cycle detection
102
+ // ---------------------------------------------------------------------------
103
+ /**
104
+ * Returns `true` if the graph contains at least one directed cycle among the
105
+ * real nodes (sentinels are excluded from cycle detection).
106
+ *
107
+ * Implemented by comparing the length of the topological sort result against
108
+ * the total number of real nodes: Kahn's algorithm processes every node in a
109
+ * DAG, so any shortfall indicates nodes trapped inside a cycle.
110
+ *
111
+ * @returns `true` when a cycle exists; `false` for a valid DAG.
112
+ */
113
+ hasCycles() {
114
+ return this.topologicalSort().length < this.nodeIds.size;
115
+ }
116
+ // ---------------------------------------------------------------------------
117
+ // Ready-node detection
118
+ // ---------------------------------------------------------------------------
119
+ /**
120
+ * Returns the ids of all real nodes that are eligible to execute next, given
121
+ * the set of nodes that have already finished (completed or skipped).
122
+ *
123
+ * A node is "ready" when:
124
+ * 1. It has not already completed or been skipped.
125
+ * 2. Every one of its predecessors is either the START sentinel or a member of
126
+ * the completed/skipped set.
127
+ *
128
+ * @param completedNodeIds - Node ids that have successfully finished execution.
129
+ * @param skippedNodeIds - Node ids that were bypassed (e.g. via conditional routing).
130
+ * @returns Array of node ids that can be dispatched for execution immediately.
131
+ */
132
+ getReadyNodes(completedNodeIds, skippedNodeIds = []) {
133
+ // Build a unified "done" set that includes the START sentinel so that nodes
134
+ // whose only predecessor is START are treated as immediately satisfiable.
135
+ const done = new Set([START, ...completedNodeIds, ...skippedNodeIds]);
136
+ const ready = [];
137
+ for (const nodeId of this.nodeIds) {
138
+ // Skip nodes that are already done.
139
+ if (done.has(nodeId))
140
+ continue;
141
+ const preds = this.predecessors.get(nodeId) ?? [];
142
+ if (preds.every(p => done.has(p))) {
143
+ ready.push(nodeId);
144
+ }
145
+ }
146
+ return ready;
147
+ }
148
+ // ---------------------------------------------------------------------------
149
+ // Reachability analysis
150
+ // ---------------------------------------------------------------------------
151
+ /**
152
+ * Returns the ids of all real nodes that are not reachable from the START
153
+ * sentinel via a BFS traversal of the adjacency list.
154
+ *
155
+ * Unreachable (orphan) nodes indicate a structural authoring error: they can
156
+ * never execute because no execution path leads to them. The runtime may
157
+ * choose to warn, error, or prune these nodes before starting a run.
158
+ *
159
+ * @returns Array of node ids that cannot be reached from START; empty for a
160
+ * well-formed graph.
161
+ */
162
+ getUnreachableNodes() {
163
+ const visited = new Set();
164
+ const queue = [START];
165
+ while (queue.length > 0) {
166
+ const current = queue.shift();
167
+ if (visited.has(current))
168
+ continue;
169
+ visited.add(current);
170
+ for (const neighbour of this.adjacency.get(current) ?? []) {
171
+ if (!visited.has(neighbour)) {
172
+ queue.push(neighbour);
173
+ }
174
+ }
175
+ }
176
+ // Return real nodes that BFS never visited.
177
+ return [...this.nodeIds].filter(id => !visited.has(id));
178
+ }
179
+ }
180
+ //# sourceMappingURL=NodeScheduler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NodeScheduler.js","sourceRoot":"","sources":["../../../src/orchestration/runtime/NodeScheduler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,122 @@
1
+ /**
2
+ * @file StateManager.ts
3
+ * @description Manages the mutable {@link GraphState} partitions for an active graph run.
4
+ *
5
+ * Responsibilities:
6
+ * - Creating a clean initial state from caller-supplied input.
7
+ * - Applying node output patches to the `scratch` partition, honoring per-field
8
+ * {@link StateReducers} for deterministic conflict resolution.
9
+ * - Applying node output patches to the `artifacts` partition (last-write-wins by default).
10
+ * - Merging states produced by parallel branches using the same reducer logic.
11
+ * - Tracking the ordered list of visited node ids and the global iteration counter.
12
+ *
13
+ * `StateManager` is intentionally stateless between calls — it receives the current
14
+ * {@link GraphState} as an argument and returns a *new* object; it never mutates in place.
15
+ * This makes it straightforward to unit-test and safe to use in concurrent contexts.
16
+ */
17
+ import type { StateReducers, GraphState } from '../ir/types.js';
18
+ /**
19
+ * Manages the {@link GraphState} partitions (`input`, `scratch`, `artifacts`,
20
+ * `memory`, `diagnostics`) for a single graph run.
21
+ *
22
+ * All methods return a *new* `GraphState` object; the original is never mutated.
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * const manager = new StateManager({ 'scratch.messages': 'concat' });
27
+ * let state = manager.initialize({ prompt: 'Hello' });
28
+ * state = manager.updateScratch(state, { messages: ['first'] });
29
+ * state = manager.updateScratch(state, { messages: ['second'] });
30
+ * // state.scratch.messages === ['first', 'second']
31
+ * ```
32
+ */
33
+ export declare class StateManager {
34
+ private readonly reducers;
35
+ /**
36
+ * @param reducers - Field-level reducer configuration keyed by dot-notation paths
37
+ * (e.g. `'scratch.messages'`). Determines how conflicting values
38
+ * are merged during {@link updateScratch} and {@link mergeParallelBranches}.
39
+ */
40
+ constructor(reducers: StateReducers);
41
+ /**
42
+ * Create a clean initial {@link GraphState} from the caller-supplied `input` value.
43
+ *
44
+ * The `input` partition is frozen with {@link Object.freeze} so that no node can
45
+ * accidentally mutate it. All other partitions start empty.
46
+ *
47
+ * @param input - Arbitrary value provided by the graph caller; becomes `state.input`.
48
+ * @returns A fully initialised `GraphState` ready for the first node execution.
49
+ */
50
+ initialize(input: unknown): GraphState;
51
+ /**
52
+ * Apply a `patch` to the `scratch` partition, honoring any registered reducers.
53
+ *
54
+ * For each key in `patch`:
55
+ * - If a reducer is registered at `scratch.<key>` **and** the key already exists
56
+ * in the current scratch, the reducer is called to merge the existing and incoming
57
+ * values.
58
+ * - Otherwise the incoming value simply overwrites (last-write-wins semantics).
59
+ *
60
+ * @param state - Current graph state (not mutated).
61
+ * @param patch - Partial scratch update emitted by a completed node.
62
+ * @returns New `GraphState` with the merged scratch partition.
63
+ */
64
+ updateScratch(state: GraphState, patch: Record<string, unknown>): GraphState;
65
+ /**
66
+ * Apply a `patch` to the `artifacts` partition using last-write-wins semantics.
67
+ *
68
+ * Artifact fields are intended for caller-facing outputs and are not subject to
69
+ * reducer logic in this method. If you need reducer-aware artifact merging, use
70
+ * {@link mergeParallelBranches} instead.
71
+ *
72
+ * @param state - Current graph state (not mutated).
73
+ * @param patch - Partial artifacts update emitted by a completed node.
74
+ * @returns New `GraphState` with the updated artifacts partition.
75
+ */
76
+ updateArtifacts(state: GraphState, patch: Record<string, unknown>): GraphState;
77
+ /**
78
+ * Record that execution has entered `nodeId`.
79
+ *
80
+ * Updates `currentNodeId`, appends to `visitedNodes`, and increments `iteration`.
81
+ *
82
+ * @param state - Current graph state (not mutated).
83
+ * @param nodeId - Id of the node that is about to execute.
84
+ * @returns New `GraphState` reflecting the visit.
85
+ */
86
+ recordNodeVisit(state: GraphState, nodeId: string): GraphState;
87
+ /**
88
+ * Merge the `scratch` partitions of one or more parallel branch states back into
89
+ * a single `GraphState`.
90
+ *
91
+ * The algorithm walks every key present in any branch's scratch object and applies
92
+ * the registered reducer for that key (if any) against the accumulator. When no
93
+ * reducer is registered, the last branch's value wins.
94
+ *
95
+ * The `artifacts`, `memory`, `diagnostics`, `visitedNodes`, and `iteration` fields
96
+ * of `baseState` are preserved unchanged — the caller is responsible for merging
97
+ * those separately if needed.
98
+ *
99
+ * @param baseState - State prior to the parallel fan-out (provides the baseline scratch).
100
+ * @param branchStates - States produced by each parallel branch.
101
+ * @returns New `GraphState` with the merged scratch partition.
102
+ */
103
+ mergeParallelBranches(baseState: GraphState, branchStates: GraphState[]): GraphState;
104
+ /**
105
+ * Dispatch to a {@link BuiltinReducer} strategy or call a custom {@link ReducerFn}.
106
+ *
107
+ * @param reducer - The reducer to apply.
108
+ * @param existing - Value currently stored in `GraphState`.
109
+ * @param incoming - New value emitted by the most recently completed node.
110
+ * @returns The merged value.
111
+ */
112
+ private applyReducer;
113
+ /**
114
+ * Construct an empty {@link MemoryView} used during state initialisation.
115
+ */
116
+ private emptyMemoryView;
117
+ /**
118
+ * Construct a zeroed {@link DiagnosticsView} used during state initialisation.
119
+ */
120
+ private emptyDiagnostics;
121
+ }
122
+ //# sourceMappingURL=StateManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StateManager.d.ts","sourceRoot":"","sources":["../../../src/orchestration/runtime/StateManager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EACV,aAAa,EAGb,UAAU,EAGX,MAAM,gBAAgB,CAAC;AAMxB;;;;;;;;;;;;;;GAcG;AACH,qBAAa,YAAY;IAMX,OAAO,CAAC,QAAQ,CAAC,QAAQ;IALrC;;;;OAIG;gBAC0B,QAAQ,EAAE,aAAa;IAMpD;;;;;;;;OAQG;IACH,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,UAAU;IAatC;;;;;;;;;;;;OAYG;IACH,aAAa,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,UAAU;IAmB5E;;;;;;;;;;OAUG;IACH,eAAe,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,UAAU;IAO9E;;;;;;;;OAQG;IACH,eAAe,CAAC,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAG,UAAU;IAS9D;;;;;;;;;;;;;;;OAeG;IACH,qBAAqB,CAAC,SAAS,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,GAAG,UAAU;IAyBpF;;;;;;;OAOG;IACH,OAAO,CAAC,YAAY;IAwDpB;;OAEG;IACH,OAAO,CAAC,eAAe;IASvB;;OAEG;IACH,OAAO,CAAC,gBAAgB;CAYzB"}