@noetic-tools/core 0.0.1 → 0.1.1

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 (254) hide show
  1. package/README.md +31 -11
  2. package/dist/adapters/in-memory-fs-adapter.d.ts +1 -1
  3. package/dist/adapters/in-memory-fs-adapter.js +1 -1
  4. package/dist/adapters/in-memory-shell-adapter.d.ts +1 -1
  5. package/dist/adapters/in-memory-subprocess/manifest-persistence.d.ts +8 -0
  6. package/dist/adapters/in-memory-subprocess/manifest-persistence.js +56 -0
  7. package/dist/adapters/in-memory-subprocess/metadata.d.ts +12 -0
  8. package/dist/adapters/in-memory-subprocess/metadata.js +58 -0
  9. package/dist/adapters/in-memory-subprocess/step-completion.d.ts +3 -0
  10. package/dist/adapters/in-memory-subprocess/step-completion.js +86 -0
  11. package/dist/adapters/in-memory-subprocess/types.d.ts +88 -0
  12. package/dist/adapters/in-memory-subprocess/types.js +2 -0
  13. package/dist/adapters/in-memory-subprocess-adapter.d.ts +12 -4
  14. package/dist/adapters/in-memory-subprocess-adapter.js +164 -55
  15. package/dist/adapters/openrouter.d.ts +16 -7
  16. package/dist/adapters/openrouter.js +68 -7
  17. package/dist/builders/channel-builder.d.ts +1 -1
  18. package/dist/builders/control-flow-builders.d.ts +3 -3
  19. package/dist/builders/control-flow-builders.js +9 -4
  20. package/dist/builders/every.d.ts +3 -3
  21. package/dist/builders/every.js +5 -2
  22. package/dist/builders/layer-provides-builders.d.ts +1 -32
  23. package/dist/builders/layer-provides-builders.js +1 -33
  24. package/dist/builders/loop-builder.d.ts +2 -2
  25. package/dist/builders/loop-builder.js +5 -2
  26. package/dist/builders/memory-builder.d.ts +1 -1
  27. package/dist/builders/memory-builder.js +1 -1
  28. package/dist/builders/provide-builder.d.ts +2 -2
  29. package/dist/builders/provide-builder.js +5 -2
  30. package/dist/builders/spawn-builder.d.ts +22 -9
  31. package/dist/builders/spawn-builder.js +17 -3
  32. package/dist/builders/step-builders.d.ts +51 -30
  33. package/dist/builders/step-builders.js +31 -12
  34. package/dist/builders/tool-builder.d.ts +7 -3
  35. package/dist/builders/tool-builder.js +3 -1
  36. package/dist/builders/workflow-hydrator.d.ts +38 -0
  37. package/dist/builders/workflow-hydrator.js +336 -0
  38. package/dist/conditions/conditions.d.ts +4 -4
  39. package/dist/conditions/conditions.js +2 -2
  40. package/dist/errors/noetic-error.d.ts +1 -1
  41. package/dist/errors/noetic-error.js +2 -0
  42. package/dist/{runtime → harness}/agent-harness.d.ts +65 -45
  43. package/dist/harness/agent-harness.js +576 -0
  44. package/dist/harness/deps/adapters.d.ts +4 -0
  45. package/dist/harness/deps/adapters.js +4 -0
  46. package/dist/harness/deps/interpreter.d.ts +5 -0
  47. package/dist/harness/deps/interpreter.js +4 -0
  48. package/dist/harness/deps/memory.d.ts +5 -0
  49. package/dist/harness/deps/memory.js +4 -0
  50. package/dist/harness/deps/runtime.d.ts +10 -0
  51. package/dist/harness/deps/runtime.js +7 -0
  52. package/dist/harness/deps/types.d.ts +17 -0
  53. package/dist/harness/deps/types.js +1 -0
  54. package/dist/harness/model-call.d.ts +50 -0
  55. package/dist/harness/model-call.js +694 -0
  56. package/dist/harness/model-schema.d.ts +19 -0
  57. package/dist/harness/model-schema.js +46 -0
  58. package/dist/harness/step-bootstrap.d.ts +25 -0
  59. package/dist/harness/step-bootstrap.js +170 -0
  60. package/dist/index.d.ts +114 -76
  61. package/dist/index.js +74 -50
  62. package/dist/internal-test.d.ts +4 -4
  63. package/dist/internal-test.js +4 -4
  64. package/dist/interpreter/action-deps.d.ts +12 -0
  65. package/dist/interpreter/action-deps.js +10 -0
  66. package/dist/interpreter/action-types.d.ts +8 -0
  67. package/dist/interpreter/action-types.js +1 -0
  68. package/dist/interpreter/collect-tools.d.ts +2 -2
  69. package/dist/interpreter/collect-tools.js +6 -2
  70. package/dist/interpreter/execute-action.d.ts +22 -0
  71. package/dist/interpreter/execute-action.js +527 -0
  72. package/dist/interpreter/{execute-every.d.ts → execute-control.d.ts} +8 -2
  73. package/dist/interpreter/execute-control.js +530 -0
  74. package/dist/interpreter/execute.d.ts +16 -3
  75. package/dist/interpreter/execute.js +154 -51
  76. package/dist/interpreter/message-helpers.d.ts +1 -9
  77. package/dist/interpreter/message-helpers.js +1 -42
  78. package/dist/interpreter/step-dispatcher.d.ts +61 -0
  79. package/dist/interpreter/step-dispatcher.js +67 -0
  80. package/dist/interpreter/typeguards.d.ts +8 -15
  81. package/dist/interpreter/typeguards.js +4 -21
  82. package/dist/memory/budget.d.ts +2 -2
  83. package/dist/memory/budget.js +1 -1
  84. package/dist/{runtime → memory}/exec-context-factory.d.ts +2 -2
  85. package/dist/{runtime → memory}/exec-context-factory.js +1 -1
  86. package/dist/memory/flow-schema.d.ts +52 -0
  87. package/dist/memory/flow-schema.js +102 -0
  88. package/dist/memory/function-call-utils.d.ts +1 -1
  89. package/dist/memory/function-call-utils.js +4 -2
  90. package/dist/memory/layer-api.d.ts +4 -4
  91. package/dist/memory/layer-api.js +2 -2
  92. package/dist/memory/layer-lifecycle.d.ts +6 -6
  93. package/dist/memory/layer-lifecycle.js +6 -6
  94. package/dist/memory/layer-provides.d.ts +32 -0
  95. package/dist/memory/layer-provides.js +33 -0
  96. package/dist/memory/layer-usage.d.ts +4 -3
  97. package/dist/memory/layer-usage.js +9 -3
  98. package/dist/memory/layers/durable-task-state.d.ts +8 -8
  99. package/dist/memory/layers/durable-task-state.js +2 -2
  100. package/dist/memory/layers/file-reference.d.ts +1 -1
  101. package/dist/memory/layers/file-reference.js +303 -247
  102. package/dist/memory/layers/history-window.d.ts +1 -1
  103. package/dist/memory/layers/history-window.js +4 -4
  104. package/dist/memory/layers/observational-memory.d.ts +5 -5
  105. package/dist/memory/layers/observational-memory.js +2 -3
  106. package/dist/memory/layers/plan.d.ts +2 -2
  107. package/dist/memory/layers/plan.js +15 -10
  108. package/dist/memory/layers/static-content.d.ts +2 -2
  109. package/dist/memory/layers/static-content.js +1 -1
  110. package/dist/memory/layers/steering.d.ts +7 -7
  111. package/dist/memory/layers/steering.js +5 -5
  112. package/dist/memory/layers/tool-memory-layer.d.ts +2 -2
  113. package/dist/memory/layers/tool-memory-layer.js +1 -1
  114. package/dist/memory/layers/working-memory.d.ts +7 -7
  115. package/dist/memory/layers/working-memory.js +4 -4
  116. package/dist/memory/projector.d.ts +2 -2
  117. package/dist/memory/scope.d.ts +1 -1
  118. package/dist/memory/strip-unresolved.d.ts +1 -1
  119. package/dist/observability/span-impl.d.ts +1 -1
  120. package/dist/observability/trace-exporter.d.ts +2 -2
  121. package/dist/observability/trace-exporter.js +1 -1
  122. package/dist/patterns/dynamic-workflow.d.ts +55 -0
  123. package/dist/patterns/dynamic-workflow.js +194 -0
  124. package/dist/patterns/flow.d.ts +2 -52
  125. package/dist/patterns/flow.js +1 -103
  126. package/dist/patterns/interview.d.ts +2 -2
  127. package/dist/patterns/interview.js +5 -5
  128. package/dist/patterns/plans.d.ts +6 -6
  129. package/dist/patterns/plans.js +4 -4
  130. package/dist/patterns/ralph-wiggum.d.ts +4 -4
  131. package/dist/patterns/ralph-wiggum.js +5 -5
  132. package/dist/patterns/react.d.ts +3 -3
  133. package/dist/patterns/react.js +5 -5
  134. package/dist/portable/adapters.d.ts +6 -0
  135. package/dist/portable/adapters.js +6 -0
  136. package/dist/portable/ask-user.d.ts +4 -0
  137. package/dist/portable/ask-user.js +2 -0
  138. package/dist/portable/builders.d.ts +12 -0
  139. package/dist/portable/builders.js +12 -0
  140. package/dist/portable/memory-layers.d.ts +12 -0
  141. package/dist/portable/memory-layers.js +12 -0
  142. package/dist/portable/runtime.d.ts +4 -0
  143. package/dist/portable/runtime.js +4 -0
  144. package/dist/portable/until.d.ts +4 -0
  145. package/dist/portable/until.js +4 -0
  146. package/dist/portable.d.ts +8 -26
  147. package/dist/portable.js +8 -34
  148. package/dist/runtime/broadcaster-utils.d.ts +7 -3
  149. package/dist/runtime/broadcaster-utils.js +11 -6
  150. package/dist/runtime/channel-store.d.ts +1 -1
  151. package/dist/runtime/channel-store.js +2 -2
  152. package/dist/runtime/context-deps.d.ts +4 -0
  153. package/dist/runtime/context-deps.js +2 -0
  154. package/dist/runtime/context-impl.d.ts +42 -12
  155. package/dist/runtime/context-impl.js +52 -5
  156. package/dist/runtime/context-type-deps.d.ts +14 -0
  157. package/dist/runtime/context-type-deps.js +1 -0
  158. package/dist/runtime/cwd-helpers.d.ts +1 -1
  159. package/dist/runtime/detached-handle.d.ts +52 -4
  160. package/dist/runtime/detached-handle.js +218 -14
  161. package/dist/runtime/durable/checkpoint-store.d.ts +38 -0
  162. package/dist/runtime/durable/checkpoint-store.js +101 -0
  163. package/dist/runtime/durable/detached-signal.d.ts +37 -0
  164. package/dist/runtime/durable/detached-signal.js +52 -0
  165. package/dist/runtime/durable/harness-checkpoints.d.ts +51 -0
  166. package/dist/runtime/durable/harness-checkpoints.js +104 -0
  167. package/dist/runtime/durable/index.d.ts +10 -0
  168. package/dist/runtime/durable/index.js +5 -0
  169. package/dist/runtime/durable/runnable-loop.d.ts +100 -0
  170. package/dist/runtime/durable/runnable-loop.js +90 -0
  171. package/dist/runtime/durable/session-seed.d.ts +28 -0
  172. package/dist/runtime/durable/session-seed.js +27 -0
  173. package/dist/runtime/durable/stall-nudge.d.ts +82 -0
  174. package/dist/runtime/durable/stall-nudge.js +87 -0
  175. package/dist/runtime/event-broadcaster.d.ts +1 -1
  176. package/dist/runtime/in-memory-storage.d.ts +1 -1
  177. package/dist/runtime/in-memory-storage.js +1 -1
  178. package/dist/runtime/item-log-impl.d.ts +3 -3
  179. package/dist/runtime/item-log-impl.js +1 -1
  180. package/dist/runtime/message-queue.d.ts +2 -2
  181. package/dist/runtime/session-runner.d.ts +7 -7
  182. package/dist/runtime/session-runner.js +3 -3
  183. package/dist/runtime/session-streams.d.ts +3 -3
  184. package/dist/runtime/session-streams.js +1 -1
  185. package/dist/runtime/step-registry.d.ts +42 -0
  186. package/dist/runtime/step-registry.js +77 -0
  187. package/dist/runtime/tool-memory.d.ts +3 -3
  188. package/dist/schemas/item.d.ts +1 -1
  189. package/dist/schemas/workflow.d.ts +139 -0
  190. package/dist/schemas/workflow.js +232 -0
  191. package/dist/types/ask-user-types.d.ts +57 -0
  192. package/dist/types/ask-user-types.js +74 -0
  193. package/dist/types/checkpoint.d.ts +98 -0
  194. package/dist/types/checkpoint.js +81 -0
  195. package/dist/types/common.d.ts +1 -50
  196. package/dist/types/context-parts/item-log.d.ts +6 -0
  197. package/dist/types/context-parts/item-log.js +1 -0
  198. package/dist/types/context-parts/layer-usage.d.ts +18 -0
  199. package/dist/types/context-parts/layer-usage.js +1 -0
  200. package/dist/types/context.d.ts +140 -31
  201. package/dist/types/error.d.ts +15 -0
  202. package/dist/types/harness-result.d.ts +2 -2
  203. package/dist/types/items.d.ts +18 -2
  204. package/dist/types/memory-context.d.ts +39 -0
  205. package/dist/types/memory-context.js +1 -0
  206. package/dist/types/memory.d.ts +38 -68
  207. package/dist/types/mutable-context.d.ts +3 -3
  208. package/dist/types/runtime.d.ts +14 -13
  209. package/dist/types/steering.d.ts +2 -2
  210. package/dist/types/step-registrar.d.ts +46 -0
  211. package/dist/types/step-registrar.js +56 -0
  212. package/dist/types/step.d.ts +34 -9
  213. package/dist/types/subprocess-adapter.d.ts +119 -3
  214. package/dist/types/subprocess-adapter.js +2 -0
  215. package/dist/types/tool-context.d.ts +6 -6
  216. package/dist/types/tool.d.ts +64 -0
  217. package/dist/types/tool.js +1 -0
  218. package/dist/unstable.d.ts +9 -9
  219. package/dist/unstable.js +7 -7
  220. package/dist/until/combinators.d.ts +1 -1
  221. package/dist/until/never.d.ts +1 -1
  222. package/dist/until/predicates.d.ts +13 -4
  223. package/dist/until/predicates.js +16 -2
  224. package/dist/util/message-helpers.d.ts +17 -0
  225. package/dist/util/message-helpers.js +64 -0
  226. package/package.json +6 -4
  227. package/dist/adapters/local-fs-adapter.d.ts +0 -3
  228. package/dist/adapters/local-fs-adapter.js +0 -43
  229. package/dist/adapters/local-shell-adapter.d.ts +0 -51
  230. package/dist/adapters/local-shell-adapter.js +0 -167
  231. package/dist/adapters/local-subprocess-adapter.d.ts +0 -16
  232. package/dist/adapters/local-subprocess-adapter.js +0 -187
  233. package/dist/conditions/index.d.ts +0 -3
  234. package/dist/conditions/index.js +0 -2
  235. package/dist/interpreter/execute-branch.d.ts +0 -3
  236. package/dist/interpreter/execute-branch.js +0 -10
  237. package/dist/interpreter/execute-every.js +0 -143
  238. package/dist/interpreter/execute-fork.d.ts +0 -3
  239. package/dist/interpreter/execute-fork.js +0 -215
  240. package/dist/interpreter/execute-llm.d.ts +0 -4
  241. package/dist/interpreter/execute-llm.js +0 -217
  242. package/dist/interpreter/execute-loop.d.ts +0 -3
  243. package/dist/interpreter/execute-loop.js +0 -171
  244. package/dist/interpreter/execute-provide.d.ts +0 -10
  245. package/dist/interpreter/execute-provide.js +0 -64
  246. package/dist/interpreter/execute-run.d.ts +0 -3
  247. package/dist/interpreter/execute-run.js +0 -39
  248. package/dist/interpreter/execute-spawn.d.ts +0 -11
  249. package/dist/interpreter/execute-spawn.js +0 -113
  250. package/dist/interpreter/execute-tool.d.ts +0 -5
  251. package/dist/interpreter/execute-tool.js +0 -81
  252. package/dist/runtime/agent-harness.js +0 -1170
  253. /package/dist/{interpreter → util}/framework-cast.d.ts +0 -0
  254. /package/dist/{interpreter → util}/framework-cast.js +0 -0
@@ -1,9 +1,9 @@
1
1
  import { z } from 'zod';
2
- import { layerData, layerFn } from '../../builders/layer-provides-builders';
3
- import { createMessage, estimateTokens } from '../../interpreter/message-helpers';
4
- import { FlowSchema, flowDepth } from '../../patterns/flow';
5
- import { Slot } from '../../types/memory';
6
- import { SteeringAction } from '../../types/steering';
2
+ import { Slot } from '../../types/memory.js';
3
+ import { SteeringAction } from '../../types/steering.js';
4
+ import { createMessage, estimateTokens } from '../../util/message-helpers.js';
5
+ import { FlowSchema, flowDepth } from '../flow-schema.js';
6
+ import { layerData, layerFn } from '../layer-provides.js';
7
7
  //#region Constants
8
8
  const MAX_PRD_LENGTH = 5e4;
9
9
  const MAX_TREE_DEPTH = 5;
@@ -14,7 +14,12 @@ const ALLOWED_TOOLS_IN_PLAN_MODE = new Set([
14
14
  'Grep',
15
15
  'Find',
16
16
  'Ls',
17
+ 'AskUserQuestion',
17
18
  'activateSkill',
19
+ 'agent',
20
+ 'checkAgent',
21
+ 'sendMessage',
22
+ 'requestPlanApproval',
18
23
  'plan/enterPlanMode',
19
24
  'plan/updatePrd',
20
25
  'plan/setPlanTree',
@@ -63,15 +68,15 @@ function trimExecutionLog(log) {
63
68
  function recallPlanning(state, additionalInstructions) {
64
69
  const sections = [
65
70
  '<plan_mode>',
66
- 'You are in PLAN MODE. You may only use read-only tools (Read, Grep, Find, Ls) to explore the codebase.',
71
+ 'You are in PLAN MODE. You may only use read-only tools (Read, Grep, Find, Ls), AskUserQuestion, skill activation, sub-agent coordination tools, and requestPlanApproval to explore the codebase and request execution approval.',
67
72
  'Your goal is to produce a PRD document and (optionally) a structured execution plan.',
68
73
  '',
69
74
  '## Workflow (5 phases)',
70
75
  '',
71
- '1. **Initial Understanding** — Read code and gather context. To parallelise exploration, fork over `{ kind: "subagent", preset: "explore", prompt: "..." }` nodes; up to 3 in parallel. Each Explore subagent returns a focused report.',
72
- '2. **Design** — Synthesise findings. Optionally invoke `{ kind: "subagent", preset: "plan", prompt: "..." }` (1–3 in parallel) to draft alternative implementation approaches and surface trade-offs.',
76
+ '1. **Initial Understanding** — Read code and gather context. To parallelise exploration, use the `agent` tool to spawn bounded read-only sub-agents; up to 3 in parallel. Each sub-agent returns a focused report.',
77
+ '2. **Design** — Synthesise findings. Optionally spawn planning sub-agents (1–3 in parallel) to draft alternative implementation approaches and surface trade-offs.',
73
78
  '3. **Review** — Read the critical files identified by your subagents directly so you understand them first-hand. If anything is ambiguous, ask the user a focused question.',
74
- '4. **Final Plan** — Write the PRD via `plan/updatePrd`. Lead with a **Context** section (why this change), then your single recommended approach, the paths of files to modify, existing functions/utilities to reuse, and a **Verification** section. If the task warrants custom step orchestration, also call `plan/setPlanTree` with a JSON noetic flow built from the existing step primitives (`step.llm`, `step.branch`, `step.fork`, `step.spawn`, `step.loop`) — tool refs by name string. Otherwise omit the tree.',
79
+ '4. **Final Plan** — Write the PRD via `plan/updatePrd`. Lead with a **Context** section (why this change), then your single recommended approach, the paths of files to modify, existing functions/utilities to reuse, and a **Verification** section. Then call `plan/setPlanTree` with a JSON noetic flow built from the existing step primitives (`step.llm`, `step.branch`, `step.fork`, `step.spawn`, `step.loop`) — tool refs by name string.',
75
80
  '5. **Exit** — Call `plan/exitPlanMode` with `{ action: "execute" }` to request approval. The user must accept before execution begins; if they reject, you stay in Plan Mode and may revise.',
76
81
  '',
77
82
  '## Available actions',
@@ -81,7 +86,7 @@ function recallPlanning(state, additionalInstructions) {
81
86
  '- `plan/exitPlanMode` `{ action: "cancel" }` — discard plan and return to idle',
82
87
  '',
83
88
  '## Constraints',
84
- '- DO NOT create, modify, or delete files (other than via `plan/updatePrd`).',
89
+ '- DO NOT create, modify, or delete files (other than via `plan/updatePrd` and `plan/setPlanTree`).',
85
90
  '- DO NOT run mutating shell commands. Read-only exploration only.',
86
91
  '- End each turn either by asking the user a focused clarifying question or by calling `plan/exitPlanMode`.',
87
92
  ];
@@ -1,4 +1,4 @@
1
- import type { MemoryScope } from '../../types/memory';
1
+ import type { MemoryScope } from '../../types/memory.js';
2
2
  interface StaticContentOpts {
3
3
  id?: string;
4
4
  slot?: number;
@@ -21,7 +21,7 @@ export declare function staticContent(opts: StaticContentOpts): {
21
21
  init(): Promise<{
22
22
  state: string;
23
23
  }>;
24
- recall({ state }: import("../..").RecallParams<string>): Promise<string | null>;
24
+ recall({ state }: import("../../index.js").RecallParams<string>): Promise<string | null>;
25
25
  };
26
26
  };
27
27
  export {};
@@ -1,4 +1,4 @@
1
- import { Slot } from '../../types/memory';
1
+ import { Slot } from '../../types/memory.js';
2
2
  /**
3
3
  * Creates a read-only memory layer that loads static content once at init and injects it into recall.
4
4
  *
@@ -1,5 +1,5 @@
1
- import type { MemoryScope } from '../../types/memory';
2
- import type { AfterModelCallParams, BeforeToolCallParams, LedgerEntry, SteeringConfig, SteeringDecision, SteeringState } from '../../types/steering';
1
+ import type { MemoryScope } from '../../types/memory.js';
2
+ import type { AfterModelCallParams, BeforeToolCallParams, LedgerEntry, SteeringConfig, SteeringDecision, SteeringState } from '../../types/steering.js';
3
3
  /**
4
4
  * Creates a steering memory layer that evaluates rules before tool calls and after model calls.
5
5
  *
@@ -21,11 +21,11 @@ export declare function steering(config: SteeringConfig): {
21
21
  afterModelCall: number;
22
22
  };
23
23
  hooks: {
24
- init({ storage }: import("../..").InitParams): Promise<{
24
+ init({ storage }: import("../../index.js").InitParams): Promise<{
25
25
  state: SteeringState;
26
26
  }>;
27
- recall({ state }: import("../..").RecallParams<SteeringState>): Promise<{
28
- items: import("../..").InputMessageItem[];
27
+ recall({ state }: import("../../index.js").RecallParams<SteeringState>): Promise<{
28
+ items: import("../../index.js").InputMessageItem[];
29
29
  tokenCount: number;
30
30
  state: SteeringState;
31
31
  } | null>;
@@ -38,13 +38,13 @@ export declare function steering(config: SteeringConfig): {
38
38
  decision: SteeringDecision;
39
39
  state: SteeringState;
40
40
  }>;
41
- onSpawn({ parentState }: import("../..").SpawnParams<SteeringState>): Promise<{
41
+ onSpawn({ parentState }: import("../../index.js").SpawnParams<SteeringState>): Promise<{
42
42
  childState: {
43
43
  ledger: LedgerEntry[];
44
44
  pendingAsync: never[];
45
45
  };
46
46
  }>;
47
- onComplete({ state, outcome }: import("../..").CompleteParams<SteeringState>): Promise<{
47
+ onComplete({ state, outcome }: import("../../index.js").CompleteParams<SteeringState>): Promise<{
48
48
  state: SteeringState;
49
49
  }>;
50
50
  };
@@ -1,8 +1,8 @@
1
- import { NoeticConfigError } from '../../errors/noetic-config-error';
2
- import { createMessage, estimateTokens, extractAssistantText, } from '../../interpreter/message-helpers';
3
- import { Slot } from '../../types/memory';
4
- import { LedgerEntryKind, SteeringAction } from '../../types/steering';
5
- import { mostRestrictive } from '../layer-lifecycle';
1
+ import { NoeticConfigError } from '../../errors/noetic-config-error.js';
2
+ import { Slot } from '../../types/memory.js';
3
+ import { LedgerEntryKind, SteeringAction } from '../../types/steering.js';
4
+ import { createMessage, estimateTokens, extractAssistantText } from '../../util/message-helpers.js';
5
+ import { mostRestrictive } from '../layer-lifecycle.js';
6
6
  //#region Constants
7
7
  const DEFAULT_MAX_LEDGER_ENTRIES = 100;
8
8
  //#endregion
@@ -1,5 +1,5 @@
1
- import type { Tool } from '../../types/common';
2
- import type { MemoryLayer } from '../../types/memory';
1
+ import type { MemoryLayer } from '../../types/memory.js';
2
+ import type { Tool } from '../../types/tool.js';
3
3
  interface ToolMemoryLayerOpts {
4
4
  slot?: number;
5
5
  }
@@ -1,4 +1,4 @@
1
- import { Slot } from '../../types/memory';
1
+ import { Slot } from '../../types/memory.js';
2
2
  const EXECUTION_SCOPE = 'execution';
3
3
  /**
4
4
  * Generates one MemoryLayer per unique memory id among the provided tools.
@@ -23,21 +23,21 @@ export declare function workingMemory(config?: WorkingMemoryConfig): {
23
23
  max: number;
24
24
  };
25
25
  provides: {
26
- snapshot: import("../..").LayerDataDecl<WorkingMemoryState, WorkingMemoryState>;
27
- update: import("../..").LayerFunctionDecl<Record<string, unknown>, void, WorkingMemoryState>;
26
+ snapshot: import("../../index.js").LayerDataDecl<WorkingMemoryState, WorkingMemoryState>;
27
+ update: import("../../index.js").LayerFunctionDecl<Record<string, unknown>, void, WorkingMemoryState>;
28
28
  };
29
29
  hooks: {
30
- init({ storage }: import("../..").InitParams): Promise<{
30
+ init({ storage }: import("../../index.js").InitParams): Promise<{
31
31
  state: WorkingMemoryState;
32
32
  }>;
33
- recall({ state }: import("../..").RecallParams<WorkingMemoryState>): Promise<{
34
- items: import("../..").InputMessageItem[];
33
+ recall({ state }: import("../../index.js").RecallParams<WorkingMemoryState>): Promise<{
34
+ items: import("../../index.js").InputMessageItem[];
35
35
  tokenCount: number;
36
36
  } | null>;
37
- store({ newItems, state }: import("../..").StoreParams<WorkingMemoryState>): Promise<{
37
+ store({ newItems, state }: import("../../index.js").StoreParams<WorkingMemoryState>): Promise<{
38
38
  state: WorkingMemoryState;
39
39
  } | undefined>;
40
- onSpawn({ parentState }: import("../..").SpawnParams<WorkingMemoryState>): Promise<{
40
+ onSpawn({ parentState }: import("../../index.js").SpawnParams<WorkingMemoryState>): Promise<{
41
41
  childState: WorkingMemoryState;
42
42
  } | null>;
43
43
  };
@@ -1,8 +1,8 @@
1
1
  import { z } from 'zod';
2
- import { layerData, layerFn } from '../../builders/layer-provides-builders';
3
- import { createMessage, estimateTokens } from '../../interpreter/message-helpers';
4
- import { Slot } from '../../types/memory';
5
- import { findFunctionCall } from '../function-call-utils';
2
+ import { Slot } from '../../types/memory.js';
3
+ import { createMessage, estimateTokens } from '../../util/message-helpers.js';
4
+ import { findFunctionCall } from '../function-call-utils.js';
5
+ import { layerData, layerFn } from '../layer-provides.js';
6
6
  function safeMerge(state, args) {
7
7
  const { __proto__: _p, constructor: _c, ...safeArgs } = args;
8
8
  if (typeof state === 'object' && state !== null) {
@@ -1,5 +1,5 @@
1
- import type { Item } from '../types/items';
2
- import type { ProjectionPolicy } from '../types/memory';
1
+ import type { Item } from '../types/items.js';
2
+ import type { ProjectionPolicy } from '../types/memory.js';
3
3
  interface AssembleViewParams {
4
4
  systemPromptItems: Item[];
5
5
  layerOutputItems: Item[];
@@ -1,3 +1,3 @@
1
- import type { ExecutionContext, MemoryScope, ScopedStorage, StorageAdapter } from '../types/memory';
1
+ import type { ExecutionContext, MemoryScope, ScopedStorage, StorageAdapter } from '../types/memory.js';
2
2
  export declare function resolveScopeKey(scope: MemoryScope, ctx: ExecutionContext): string;
3
3
  export declare function createScopedStorage(storage: StorageAdapter, layerId: string, scopeKey: string): ScopedStorage;
@@ -8,6 +8,6 @@
8
8
  * session-resume path to drop dangling pairs left by a crash, and by the
9
9
  * `historyWindow` memory layer to clean orphans at the slice boundary.
10
10
  */
11
- import type { Item } from '../types/items';
11
+ import type { Item } from '../types/items.js';
12
12
  /** @public */
13
13
  export declare function stripUnresolvedToolCalls(items: ReadonlyArray<Item>): Item[];
@@ -1,4 +1,4 @@
1
- import type { Span } from '../types/observability';
1
+ import type { Span } from '../types/observability.js';
2
2
  export declare class SpanImpl implements Span {
3
3
  readonly traceId: string;
4
4
  readonly spanId: string;
@@ -1,5 +1,5 @@
1
- import type { Span, TraceExporter } from '../types/observability';
2
- import { SpanImpl } from './span-impl';
1
+ import type { Span, TraceExporter } from '../types/observability.js';
2
+ import { SpanImpl } from './span-impl.js';
3
3
  /** @public No-op trace exporter that silently discards all spans. */
4
4
  export declare class NoopExporter implements TraceExporter {
5
5
  export(_spans: Span[]): Promise<void>;
@@ -1,4 +1,4 @@
1
- import { SpanImpl } from './span-impl';
1
+ import { SpanImpl } from './span-impl.js';
2
2
  /** @public No-op trace exporter that silently discards all spans. */
3
3
  export class NoopExporter {
4
4
  async export(_spans) {
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Pattern that lets an LLM generate a workflow as JSON during execution,
3
+ * then hydrates and runs it within the same harness session.
4
+ */
5
+ import type { Context } from '../types/context.js';
6
+ import type { ContextMemory } from '../types/memory.js';
7
+ import type { AgentHarnessContract } from '../types/runtime.js';
8
+ import type { Step } from '../types/step.js';
9
+ import type { Tool } from '../types/tool.js';
10
+ /** @public Options for creating a dynamic workflow step. */
11
+ export interface DynamicWorkflowOpts {
12
+ model?: string;
13
+ instructions?: string;
14
+ tools: Tool[];
15
+ maxDepth?: number;
16
+ maxRevisions?: number;
17
+ }
18
+ /**
19
+ * Creates a step that uses an LLM to generate a workflow as JSON, then
20
+ * hydrates and executes it. The entire plan-and-execute cycle happens
21
+ * within a single harness run.
22
+ *
23
+ * @public
24
+ * @param opts.model - Model for the planner LLM. Default: `openai/gpt-4o`.
25
+ * @param opts.instructions - Additional instructions prepended to the planner prompt.
26
+ * @param opts.tools - Tools the generated workflow may reference by name.
27
+ * @param opts.maxDepth - Maximum workflow tree depth. Default: 5.
28
+ * @param opts.maxRevisions - Retries with error feedback on validation failure. Default: 3.
29
+ * @returns A `Step` that dynamically plans and executes.
30
+ */
31
+ export declare function dynamicWorkflow(opts: DynamicWorkflowOpts): Step<ContextMemory, string, string>;
32
+ /** @public Options for `parseAndRunWorkflow`. */
33
+ export interface ParseAndRunWorkflowOpts {
34
+ json: unknown;
35
+ harness: AgentHarnessContract;
36
+ ctx: Context;
37
+ tools: Tool[];
38
+ input?: string;
39
+ maxDepth?: number;
40
+ }
41
+ /**
42
+ * Parses raw JSON into a `WorkflowDocument`, hydrates it into a live step
43
+ * tree, and executes it via the harness.
44
+ *
45
+ * @public
46
+ * @param opts.json - Raw JSON (string or parsed object) representing a workflow.
47
+ * @param opts.harness - The agent harness to execute the workflow with.
48
+ * @param opts.ctx - Execution context.
49
+ * @param opts.tools - Available tools the workflow may reference.
50
+ * @param opts.maxDepth - Maximum workflow tree depth. Default: 5.
51
+ * @returns The string output of the executed workflow.
52
+ * @throws `NoeticConfigError` with code `WORKFLOW_VALIDATION_FAILED` if JSON is invalid.
53
+ * @throws `NoeticConfigError` with code `UNKNOWN_TOOL_REFERENCE` if a tool reference cannot be resolved.
54
+ */
55
+ export declare function parseAndRunWorkflow(opts: ParseAndRunWorkflowOpts): Promise<string>;
@@ -0,0 +1,194 @@
1
+ /**
2
+ * Pattern that lets an LLM generate a workflow as JSON during execution,
3
+ * then hydrates and runs it within the same harness session.
4
+ */
5
+ import { step } from '../builders/step-builders.js';
6
+ import { hydrateWorkflow } from '../builders/workflow-hydrator.js';
7
+ import { NoeticConfigError } from '../errors/noetic-config-error.js';
8
+ import { WorkflowDocumentSchema, workflowDepth } from '../schemas/workflow.js';
9
+ import { frameworkCast } from '../util/framework-cast.js';
10
+ //#endregion
11
+ //#region Constants
12
+ const DEFAULT_MAX_DEPTH = 5;
13
+ const DEFAULT_MAX_REVISIONS = 3;
14
+ const DEFAULT_MODEL = 'openai/gpt-4o';
15
+ const PLANNER_INSTRUCTIONS = `You are a workflow planner. Given a task, generate a JSON workflow document that describes how to accomplish it.
16
+
17
+ The workflow document must be valid JSON with this structure:
18
+ {
19
+ "version": 1,
20
+ "root": <WorkflowNode>
21
+ }
22
+
23
+ A WorkflowNode is one of:
24
+ - { "kind": "llm", "id": "<unique>", "instructions": "<prompt>", "model": "<optional>", "tools": ["<tool-name>", ...] }
25
+ - { "kind": "tool", "id": "<unique>", "toolName": "<name>", "args": { ... } }
26
+ - { "kind": "sequence", "id": "<unique>", "steps": [<WorkflowNode>, ...] }
27
+ - { "kind": "fork", "id": "<unique>", "mode": "all"|"race"|"settle", "paths": [<WorkflowNode>, ...], "merge": "last"|"first"|"concat" }
28
+ - { "kind": "loop", "id": "<unique>", "body": <WorkflowNode>, "until": { "kind": "maxSteps", "n": <number> } }
29
+ - { "kind": "branch", "id": "<unique>", "routes": [{ "match": "<substring>", "target": <WorkflowNode> }], "default": <WorkflowNode> }
30
+ - { "kind": "spawn", "id": "<unique>", "child": <WorkflowNode> }
31
+
32
+ Until predicates: maxSteps, maxCost, maxDuration, noToolCalls, outputContains, outputEquals, converged, any, all.
33
+
34
+ Respond with ONLY the JSON document, no markdown fences or explanation.`;
35
+ //#endregion
36
+ //#region Public API
37
+ /**
38
+ * Creates a step that uses an LLM to generate a workflow as JSON, then
39
+ * hydrates and executes it. The entire plan-and-execute cycle happens
40
+ * within a single harness run.
41
+ *
42
+ * @public
43
+ * @param opts.model - Model for the planner LLM. Default: `openai/gpt-4o`.
44
+ * @param opts.instructions - Additional instructions prepended to the planner prompt.
45
+ * @param opts.tools - Tools the generated workflow may reference by name.
46
+ * @param opts.maxDepth - Maximum workflow tree depth. Default: 5.
47
+ * @param opts.maxRevisions - Retries with error feedback on validation failure. Default: 3.
48
+ * @returns A `Step` that dynamically plans and executes.
49
+ */
50
+ export function dynamicWorkflow(opts) {
51
+ const model = opts.model ?? DEFAULT_MODEL;
52
+ const maxDepth = opts.maxDepth ?? DEFAULT_MAX_DEPTH;
53
+ const maxRevisions = opts.maxRevisions ?? DEFAULT_MAX_REVISIONS;
54
+ const toolMap = buildToolMap(opts.tools);
55
+ return step.run({
56
+ id: 'dynamic-workflow',
57
+ execute: async (input, ctx) => {
58
+ const harness = ctx.harness;
59
+ if (!harness) {
60
+ throw new NoeticConfigError({
61
+ code: 'MISSING_HARNESS_CONTEXT',
62
+ message: 'dynamicWorkflow requires a harness on the execution context.',
63
+ hint: 'Execute this step via AgentHarness.run() or ensure ctx.harness is set.',
64
+ });
65
+ }
66
+ const toolList = opts.tools.map((t) => `- ${t.name}: ${t.description}`).join('\n');
67
+ const basePrompt = [
68
+ opts.instructions,
69
+ PLANNER_INSTRUCTIONS,
70
+ `\nAvailable tools:\n${toolList}`,
71
+ `\nTask: ${input}`,
72
+ ]
73
+ .filter(Boolean)
74
+ .join('\n\n');
75
+ let lastError;
76
+ for (let revision = 0; revision < maxRevisions; revision++) {
77
+ const prompt = lastError
78
+ ? `${basePrompt}\n\nPrevious attempt failed with error: ${lastError}\nPlease fix the workflow and try again.`
79
+ : basePrompt;
80
+ const plannerStep = step.llm({
81
+ id: `dynamic-workflow-planner-${revision}`,
82
+ model,
83
+ instructions: prompt,
84
+ });
85
+ const executeStep = frameworkCast(harness.run.bind(harness));
86
+ const rawOutput = await executeStep(plannerStep, input, ctx);
87
+ const text = coerceToString(rawOutput);
88
+ const parseResult = tryParseWorkflow(text, maxDepth);
89
+ if (!parseResult.ok) {
90
+ lastError = parseResult.error;
91
+ if (revision === maxRevisions - 1) {
92
+ throw new NoeticConfigError({
93
+ code: 'WORKFLOW_VALIDATION_FAILED',
94
+ message: `Failed to generate valid workflow after ${maxRevisions} attempts: ${lastError}`,
95
+ hint: 'The planner model may need clearer instructions or a more capable model.',
96
+ });
97
+ }
98
+ continue;
99
+ }
100
+ const hydrationCtx = {
101
+ tools: toolMap,
102
+ executeStep,
103
+ };
104
+ const hydrated = hydrateWorkflow(parseResult.doc, hydrationCtx);
105
+ return frameworkCast(await executeStep(hydrated, input, ctx));
106
+ }
107
+ throw new NoeticConfigError({
108
+ code: 'WORKFLOW_VALIDATION_FAILED',
109
+ message: `Failed to generate valid workflow after ${maxRevisions} attempts.`,
110
+ hint: 'The planner model may need clearer instructions or a more capable model.',
111
+ });
112
+ },
113
+ });
114
+ }
115
+ /**
116
+ * Parses raw JSON into a `WorkflowDocument`, hydrates it into a live step
117
+ * tree, and executes it via the harness.
118
+ *
119
+ * @public
120
+ * @param opts.json - Raw JSON (string or parsed object) representing a workflow.
121
+ * @param opts.harness - The agent harness to execute the workflow with.
122
+ * @param opts.ctx - Execution context.
123
+ * @param opts.tools - Available tools the workflow may reference.
124
+ * @param opts.maxDepth - Maximum workflow tree depth. Default: 5.
125
+ * @returns The string output of the executed workflow.
126
+ * @throws `NoeticConfigError` with code `WORKFLOW_VALIDATION_FAILED` if JSON is invalid.
127
+ * @throws `NoeticConfigError` with code `UNKNOWN_TOOL_REFERENCE` if a tool reference cannot be resolved.
128
+ */
129
+ export async function parseAndRunWorkflow(opts) {
130
+ const parseResult = tryParseWorkflow(opts.json, opts.maxDepth ?? DEFAULT_MAX_DEPTH);
131
+ if (!parseResult.ok) {
132
+ throw new NoeticConfigError({
133
+ code: 'WORKFLOW_VALIDATION_FAILED',
134
+ message: `Invalid workflow document: ${parseResult.error}`,
135
+ hint: 'Ensure the JSON matches the WorkflowDocumentSchema.',
136
+ });
137
+ }
138
+ const executeStep = frameworkCast(opts.harness.run.bind(opts.harness));
139
+ const hydrationCtx = {
140
+ tools: buildToolMap(opts.tools),
141
+ executeStep,
142
+ };
143
+ const hydrated = hydrateWorkflow(parseResult.doc, hydrationCtx);
144
+ const result = await executeStep(hydrated, opts.input ?? '', opts.ctx);
145
+ return coerceToString(result);
146
+ }
147
+ function buildToolMap(tools) {
148
+ return new Map(tools.map((t) => [
149
+ t.name,
150
+ t,
151
+ ]));
152
+ }
153
+ function coerceToString(value) {
154
+ if (typeof value === 'string') {
155
+ return value;
156
+ }
157
+ return String(value ?? '');
158
+ }
159
+ function tryParseWorkflow(raw, maxDepth) {
160
+ const parsed = typeof raw === 'string' ? safeParse(raw) : raw;
161
+ if (parsed === null) {
162
+ return {
163
+ ok: false,
164
+ error: 'Input is not valid JSON.',
165
+ };
166
+ }
167
+ const result = WorkflowDocumentSchema.safeParse(parsed);
168
+ if (!result.success) {
169
+ return {
170
+ ok: false,
171
+ error: result.error.message,
172
+ };
173
+ }
174
+ const depth = workflowDepth(result.data.root);
175
+ if (depth > maxDepth) {
176
+ return {
177
+ ok: false,
178
+ error: `Workflow tree depth ${depth} exceeds maximum ${maxDepth}.`,
179
+ };
180
+ }
181
+ return {
182
+ ok: true,
183
+ doc: result.data,
184
+ };
185
+ }
186
+ function safeParse(text) {
187
+ try {
188
+ return JSON.parse(text);
189
+ }
190
+ catch {
191
+ return null;
192
+ }
193
+ }
194
+ //#endregion
@@ -1,52 +1,2 @@
1
- /**
2
- * Zod schema for plan-mode flow JSON.
3
- *
4
- * A "flow" is a JSON-serialisable subset of noetic's `Step` shape that the model
5
- * may emit during plan mode. The runtime expands each node into a concrete `Step`
6
- * via the existing builders (`step.llm`, `fork`, `spawn`) at execute time.
7
- *
8
- * Tool references inside `llm` nodes are name strings — they get resolved against
9
- * the harness's live tool registry when the flow runs.
10
- */
11
- import { z } from 'zod';
12
- interface NodeBase {
13
- id: string;
14
- subPlanRef?: string;
15
- }
16
- export interface LlmFlowNode extends NodeBase {
17
- kind: 'llm';
18
- model?: string;
19
- instructions: string;
20
- tools?: string[];
21
- }
22
- export interface SubagentFlowNode extends NodeBase {
23
- kind: 'subagent';
24
- preset: string;
25
- prompt: string;
26
- }
27
- export interface ForkFlowNode extends NodeBase {
28
- kind: 'fork';
29
- mode: 'all' | 'race' | 'settle';
30
- paths: FlowNode[];
31
- }
32
- export interface SpawnFlowNode extends NodeBase {
33
- kind: 'spawn';
34
- child: FlowNode;
35
- }
36
- export interface SequenceFlowNode extends NodeBase {
37
- kind: 'sequence';
38
- steps: FlowNode[];
39
- }
40
- export type FlowNode = LlmFlowNode | SubagentFlowNode | ForkFlowNode | SpawnFlowNode | SequenceFlowNode;
41
- /** Top-level flow document — a single root node. */
42
- export declare const FlowSchema: z.ZodType<FlowNode, unknown, z.core.$ZodTypeInternals<FlowNode, unknown>>;
43
- /** Validates a candidate flow document. Throws `ZodError` on invalid input. */
44
- export declare function validateFlow(input: unknown): FlowNode;
45
- /** Walks a flow tree depth-first, yielding each node. */
46
- export declare function walkFlow(root: FlowNode): Iterable<FlowNode>;
47
- /**
48
- * Returns the maximum depth of a flow tree. A leaf (llm/subagent) is depth 0.
49
- * Structural nodes (sequence/fork/spawn) contribute +1 over their deepest child.
50
- */
51
- export declare function flowDepth(node: FlowNode): number;
52
- export {};
1
+ export type { FlowNode, ForkFlowNode, LlmFlowNode, SequenceFlowNode, SpawnFlowNode, SubagentFlowNode, } from '../memory/flow-schema.js';
2
+ export { FlowSchema, flowDepth, validateFlow, walkFlow } from '../memory/flow-schema.js';
@@ -1,103 +1 @@
1
- /**
2
- * Zod schema for plan-mode flow JSON.
3
- *
4
- * A "flow" is a JSON-serialisable subset of noetic's `Step` shape that the model
5
- * may emit during plan mode. The runtime expands each node into a concrete `Step`
6
- * via the existing builders (`step.llm`, `fork`, `spawn`) at execute time.
7
- *
8
- * Tool references inside `llm` nodes are name strings — they get resolved against
9
- * the harness's live tool registry when the flow runs.
10
- */
11
- import { z } from 'zod';
12
- //#endregion
13
- //#region Schema
14
- const FlowNodeRef = z.lazy(() => FlowNodeSchema);
15
- const SHARED_FIELDS = {
16
- id: z.string().min(1),
17
- subPlanRef: z.string().optional(),
18
- };
19
- const LlmNodeSchema = z.object({
20
- kind: z.literal('llm'),
21
- ...SHARED_FIELDS,
22
- model: z.string().optional(),
23
- instructions: z.string(),
24
- tools: z.array(z.string()).optional(),
25
- });
26
- const SubagentNodeSchema = z.object({
27
- kind: z.literal('subagent'),
28
- ...SHARED_FIELDS,
29
- preset: z.string().min(1),
30
- prompt: z.string(),
31
- });
32
- const ForkNodeSchema = z.object({
33
- kind: z.literal('fork'),
34
- ...SHARED_FIELDS,
35
- mode: z.enum([
36
- 'all',
37
- 'race',
38
- 'settle',
39
- ]),
40
- paths: z.array(FlowNodeRef).min(1),
41
- });
42
- const SpawnNodeSchema = z.object({
43
- kind: z.literal('spawn'),
44
- ...SHARED_FIELDS,
45
- child: FlowNodeRef,
46
- });
47
- const SequenceNodeSchema = z.object({
48
- kind: z.literal('sequence'),
49
- ...SHARED_FIELDS,
50
- steps: z.array(FlowNodeRef).min(1),
51
- });
52
- const FlowNodeSchema = z.discriminatedUnion('kind', [
53
- LlmNodeSchema,
54
- SubagentNodeSchema,
55
- ForkNodeSchema,
56
- SpawnNodeSchema,
57
- SequenceNodeSchema,
58
- ]);
59
- /** Top-level flow document — a single root node. */
60
- export const FlowSchema = FlowNodeSchema;
61
- //#endregion
62
- //#region Public API
63
- /** Validates a candidate flow document. Throws `ZodError` on invalid input. */
64
- export function validateFlow(input) {
65
- return FlowSchema.parse(input);
66
- }
67
- /** Walks a flow tree depth-first, yielding each node. */
68
- export function* walkFlow(root) {
69
- yield root;
70
- if (root.kind === 'fork') {
71
- for (const path of root.paths) {
72
- yield* walkFlow(path);
73
- }
74
- return;
75
- }
76
- if (root.kind === 'sequence') {
77
- for (const step of root.steps) {
78
- yield* walkFlow(step);
79
- }
80
- return;
81
- }
82
- if (root.kind === 'spawn') {
83
- yield* walkFlow(root.child);
84
- return;
85
- }
86
- }
87
- /**
88
- * Returns the maximum depth of a flow tree. A leaf (llm/subagent) is depth 0.
89
- * Structural nodes (sequence/fork/spawn) contribute +1 over their deepest child.
90
- */
91
- export function flowDepth(node) {
92
- if (node.kind === 'sequence') {
93
- return 1 + Math.max(0, ...node.steps.map(flowDepth));
94
- }
95
- if (node.kind === 'fork') {
96
- return 1 + Math.max(0, ...node.paths.map(flowDepth));
97
- }
98
- if (node.kind === 'spawn') {
99
- return 1 + flowDepth(node.child);
100
- }
101
- return 0;
102
- }
103
- //#endregion
1
+ export { FlowSchema, flowDepth, validateFlow, walkFlow } from '../memory/flow-schema.js';