@noetic-tools/core 0.2.1 → 1.0.0

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 (207) hide show
  1. package/dist/adapters/in-memory-fs-adapter.d.ts +1 -1
  2. package/dist/adapters/in-memory-fs-adapter.js +1 -1
  3. package/dist/adapters/in-memory-shell-adapter.d.ts +1 -1
  4. package/dist/adapters/in-memory-subprocess/manifest-persistence.d.ts +2 -2
  5. package/dist/adapters/in-memory-subprocess/metadata.d.ts +1 -1
  6. package/dist/adapters/in-memory-subprocess/types.d.ts +2 -2
  7. package/dist/adapters/in-memory-subprocess-adapter.d.ts +1 -1
  8. package/dist/adapters/openrouter.d.ts +2 -6
  9. package/dist/adapters/openrouter.js +1 -4
  10. package/dist/builders/channel-builder.d.ts +1 -1
  11. package/dist/builders/control-flow-builders.d.ts +2 -3
  12. package/dist/builders/control-flow-builders.js +1 -2
  13. package/dist/builders/every.d.ts +2 -3
  14. package/dist/builders/every.js +1 -1
  15. package/dist/builders/layer-provides-builders.d.ts +1 -1
  16. package/dist/builders/layer-provides-builders.js +1 -1
  17. package/dist/builders/loop-builder.d.ts +2 -2
  18. package/dist/builders/loop-builder.js +1 -1
  19. package/dist/builders/memory-builder.d.ts +1 -1
  20. package/dist/builders/memory-builder.js +1 -1
  21. package/dist/builders/provide-builder.d.ts +2 -2
  22. package/dist/builders/provide-builder.js +1 -1
  23. package/dist/builders/spawn-builder.d.ts +2 -3
  24. package/dist/builders/spawn-builder.js +1 -1
  25. package/dist/builders/step-builders.d.ts +2 -6
  26. package/dist/builders/step-builders.js +1 -1
  27. package/dist/builders/tool-builder.d.ts +1 -3
  28. package/dist/builders/tool-builder.js +1 -1
  29. package/dist/builders/workflow-hydrator.d.ts +2 -3
  30. package/dist/builders/workflow-hydrator.js +1 -2
  31. package/dist/conditions/conditions.d.ts +2 -3
  32. package/dist/conditions/conditions.js +1 -1
  33. package/dist/harness/agent-harness.d.ts +15 -5
  34. package/dist/harness/agent-harness.js +65 -10
  35. package/dist/harness/deps/memory.d.ts +2 -5
  36. package/dist/harness/deps/memory.js +1 -4
  37. package/dist/harness/deps/types.d.ts +3 -16
  38. package/dist/harness/deps/types.js +1 -1
  39. package/dist/harness/model-call.d.ts +1 -3
  40. package/dist/harness/model-call.js +10 -10
  41. package/dist/harness/model-schema.d.ts +10 -4
  42. package/dist/harness/model-schema.js +9 -1
  43. package/dist/index.d.ts +28 -49
  44. package/dist/index.js +9 -27
  45. package/dist/interpreter/action-deps.d.ts +4 -8
  46. package/dist/interpreter/action-deps.js +2 -6
  47. package/dist/interpreter/action-types.d.ts +3 -8
  48. package/dist/interpreter/action-types.js +1 -1
  49. package/dist/interpreter/collect-tools.d.ts +1 -2
  50. package/dist/interpreter/collect-tools.js +1 -1
  51. package/dist/interpreter/execute-action.js +122 -27
  52. package/dist/interpreter/execute-control.d.ts +1 -2
  53. package/dist/interpreter/execute-control.js +60 -7
  54. package/dist/interpreter/execute.d.ts +2 -3
  55. package/dist/interpreter/execute.js +1 -2
  56. package/dist/interpreter/message-helpers.d.ts +1 -1
  57. package/dist/interpreter/message-helpers.js +1 -1
  58. package/dist/interpreter/step-dispatcher.d.ts +2 -5
  59. package/dist/interpreter/typeguards.d.ts +3 -4
  60. package/dist/interpreter/typeguards.js +1 -1
  61. package/dist/observability/span-impl.d.ts +1 -1
  62. package/dist/observability/trace-exporter.d.ts +1 -1
  63. package/dist/patterns/dynamic-workflow.d.ts +2 -5
  64. package/dist/patterns/dynamic-workflow.js +1 -2
  65. package/dist/patterns/flow.d.ts +2 -2
  66. package/dist/patterns/flow.js +1 -1
  67. package/dist/patterns/interview.d.ts +2 -2
  68. package/dist/patterns/interview.js +1 -1
  69. package/dist/patterns/plans.d.ts +2 -3
  70. package/dist/patterns/plans.js +1 -1
  71. package/dist/patterns/ralph-wiggum.d.ts +2 -3
  72. package/dist/patterns/react.d.ts +2 -3
  73. package/dist/portable/memory-layers.d.ts +1 -7
  74. package/dist/portable/memory-layers.js +1 -7
  75. package/dist/portable.d.ts +2 -2
  76. package/dist/portable.js +2 -2
  77. package/dist/runtime/broadcaster-utils.d.ts +1 -1
  78. package/dist/runtime/channel-store.d.ts +43 -3
  79. package/dist/runtime/channel-store.js +233 -37
  80. package/dist/runtime/context-deps.d.ts +3 -3
  81. package/dist/runtime/context-deps.js +2 -2
  82. package/dist/runtime/context-impl.d.ts +17 -1
  83. package/dist/runtime/context-impl.js +30 -3
  84. package/dist/runtime/context-type-deps.d.ts +2 -11
  85. package/dist/runtime/cwd-helpers.d.ts +1 -1
  86. package/dist/runtime/detached-handle.d.ts +2 -3
  87. package/dist/runtime/detached-handle.js +1 -3
  88. package/dist/runtime/durable/checkpoint-store.d.ts +1 -1
  89. package/dist/runtime/durable/checkpoint-store.js +1 -1
  90. package/dist/runtime/durable/harness-checkpoints.d.ts +2 -5
  91. package/dist/runtime/durable/runnable-loop.d.ts +1 -3
  92. package/dist/runtime/durable/session-seed.d.ts +1 -1
  93. package/dist/runtime/durable/stall-nudge.d.ts +17 -10
  94. package/dist/runtime/durable/stall-nudge.js +29 -10
  95. package/dist/runtime/event-broadcaster.d.ts +10 -2
  96. package/dist/runtime/event-broadcaster.js +43 -19
  97. package/dist/runtime/in-memory-storage.d.ts +1 -1
  98. package/dist/runtime/in-memory-storage.js +1 -1
  99. package/dist/runtime/item-log-impl.d.ts +1 -3
  100. package/dist/runtime/item-log-impl.js +1 -1
  101. package/dist/runtime/message-queue.d.ts +1 -2
  102. package/dist/runtime/session-runner.d.ts +1 -4
  103. package/dist/runtime/session-streams.d.ts +1 -2
  104. package/dist/runtime/session-streams.js +1 -1
  105. package/dist/runtime/step-registry.d.ts +2 -2
  106. package/dist/runtime/step-registry.js +1 -2
  107. package/dist/runtime/tool-memory.d.ts +1 -3
  108. package/dist/types/mutable-context.d.ts +2 -3
  109. package/dist/types/step-registrar.d.ts +1 -1
  110. package/dist/unstable.d.ts +5 -9
  111. package/dist/unstable.js +3 -6
  112. package/dist/until/combinators.d.ts +1 -1
  113. package/dist/until/never.d.ts +1 -1
  114. package/dist/until/predicates.d.ts +2 -2
  115. package/package.json +4 -2
  116. package/dist/errors/noetic-config-error.d.ts +0 -41
  117. package/dist/errors/noetic-config-error.js +0 -44
  118. package/dist/errors/noetic-error.d.ts +0 -18
  119. package/dist/errors/noetic-error.js +0 -54
  120. package/dist/memory/budget.d.ts +0 -23
  121. package/dist/memory/budget.js +0 -117
  122. package/dist/memory/exec-context-factory.d.ts +0 -25
  123. package/dist/memory/exec-context-factory.js +0 -30
  124. package/dist/memory/flow-schema.d.ts +0 -52
  125. package/dist/memory/flow-schema.js +0 -102
  126. package/dist/memory/function-call-utils.d.ts +0 -6
  127. package/dist/memory/function-call-utils.js +0 -27
  128. package/dist/memory/layer-api.d.ts +0 -14
  129. package/dist/memory/layer-api.js +0 -91
  130. package/dist/memory/layer-lifecycle.d.ts +0 -160
  131. package/dist/memory/layer-lifecycle.js +0 -552
  132. package/dist/memory/layer-provides.d.ts +0 -32
  133. package/dist/memory/layer-provides.js +0 -33
  134. package/dist/memory/layer-usage.d.ts +0 -16
  135. package/dist/memory/layer-usage.js +0 -54
  136. package/dist/memory/layers/durable-task-state.d.ts +0 -79
  137. package/dist/memory/layers/durable-task-state.js +0 -118
  138. package/dist/memory/layers/file-reference.d.ts +0 -55
  139. package/dist/memory/layers/file-reference.js +0 -594
  140. package/dist/memory/layers/history-window.d.ts +0 -29
  141. package/dist/memory/layers/history-window.js +0 -114
  142. package/dist/memory/layers/observational-memory.d.ts +0 -53
  143. package/dist/memory/layers/observational-memory.js +0 -109
  144. package/dist/memory/layers/plan.d.ts +0 -55
  145. package/dist/memory/layers/plan.js +0 -374
  146. package/dist/memory/layers/static-content.d.ts +0 -27
  147. package/dist/memory/layers/static-content.js +0 -35
  148. package/dist/memory/layers/steering.d.ts +0 -51
  149. package/dist/memory/layers/steering.js +0 -258
  150. package/dist/memory/layers/temporal.d.ts +0 -91
  151. package/dist/memory/layers/temporal.js +0 -245
  152. package/dist/memory/layers/tool-memory-layer.d.ts +0 -16
  153. package/dist/memory/layers/tool-memory-layer.js +0 -43
  154. package/dist/memory/layers/working-memory.d.ts +0 -44
  155. package/dist/memory/layers/working-memory.js +0 -92
  156. package/dist/memory/projector.d.ts +0 -10
  157. package/dist/memory/projector.js +0 -19
  158. package/dist/memory/scope.d.ts +0 -3
  159. package/dist/memory/scope.js +0 -31
  160. package/dist/memory/strip-unresolved.d.ts +0 -13
  161. package/dist/memory/strip-unresolved.js +0 -35
  162. package/dist/schemas/item.d.ts +0 -35
  163. package/dist/schemas/item.js +0 -155
  164. package/dist/types/channel.d.ts +0 -29
  165. package/dist/types/channel.js +0 -1
  166. package/dist/types/common.d.ts +0 -68
  167. package/dist/types/common.js +0 -1
  168. package/dist/types/context-parts/item-log.d.ts +0 -6
  169. package/dist/types/context-parts/item-log.js +0 -1
  170. package/dist/types/context-parts/layer-usage.d.ts +0 -18
  171. package/dist/types/context-parts/layer-usage.js +0 -1
  172. package/dist/types/context.d.ts +0 -202
  173. package/dist/types/context.js +0 -1
  174. package/dist/types/detached.d.ts +0 -17
  175. package/dist/types/detached.js +0 -7
  176. package/dist/types/error.d.ts +0 -66
  177. package/dist/types/error.js +0 -1
  178. package/dist/types/fs-adapter.d.ts +0 -51
  179. package/dist/types/fs-adapter.js +0 -3
  180. package/dist/types/harness-result.d.ts +0 -43
  181. package/dist/types/harness-result.js +0 -2
  182. package/dist/types/items.d.ts +0 -131
  183. package/dist/types/items.js +0 -2
  184. package/dist/types/memory-context.d.ts +0 -39
  185. package/dist/types/memory-context.js +0 -1
  186. package/dist/types/memory.d.ts +0 -306
  187. package/dist/types/memory.js +0 -13
  188. package/dist/types/observability.d.ts +0 -30
  189. package/dist/types/observability.js +0 -1
  190. package/dist/types/runtime.d.ts +0 -256
  191. package/dist/types/runtime.js +0 -1
  192. package/dist/types/shell-adapter.d.ts +0 -34
  193. package/dist/types/shell-adapter.js +0 -10
  194. package/dist/types/steering.d.ts +0 -89
  195. package/dist/types/steering.js +0 -14
  196. package/dist/types/step.d.ts +0 -231
  197. package/dist/types/step.js +0 -1
  198. package/dist/types/subprocess-adapter.d.ts +0 -157
  199. package/dist/types/subprocess-adapter.js +0 -3
  200. package/dist/types/tool-context.d.ts +0 -34
  201. package/dist/types/tool-context.js +0 -1
  202. package/dist/types/tool.d.ts +0 -64
  203. package/dist/types/tool.js +0 -1
  204. package/dist/util/framework-cast.d.ts +0 -10
  205. package/dist/util/framework-cast.js +0 -16
  206. package/dist/util/message-helpers.d.ts +0 -17
  207. package/dist/util/message-helpers.js +0 -64
@@ -1,552 +0,0 @@
1
- import { NoeticConfigError } from '../errors/noetic-config-error.js';
2
- import { defaultItemSchemaRegistry } from '../schemas/item.js';
3
- import { SteeringAction } from '../types/steering.js';
4
- import { frameworkCast } from '../util/framework-cast.js';
5
- import { createMessage, estimateTokens } from '../util/message-helpers.js';
6
- import { createScopedStorage, resolveScopeKey } from './scope.js';
7
- /** Maximum allowed re-render depth to prevent infinite loops */
8
- const MAX_RERENDER_DEPTH = 3;
9
- /**
10
- * Default per-layer token budget when a layer has no `budget` config or uses
11
- * `'auto'`. Big enough that budget-respecting layers (e.g. file-reference)
12
- * render their content; real auto-allocation across layers is future work.
13
- */
14
- const DEFAULT_LAYER_BUDGET = 1.6e4;
15
- /** Resolve each layer's `BudgetConfig` to a concrete token budget for recall. */
16
- export function resolveLayerBudgets(layers) {
17
- const budgets = new Map();
18
- for (const layer of layers) {
19
- const cfg = layer.budget;
20
- if (typeof cfg === 'number') {
21
- budgets.set(layer.id, cfg);
22
- continue;
23
- }
24
- if (typeof cfg === 'object') {
25
- budgets.set(layer.id, cfg.max);
26
- continue;
27
- }
28
- // 'auto' or undefined → use the default ceiling.
29
- budgets.set(layer.id, DEFAULT_LAYER_BUDGET);
30
- }
31
- return budgets;
32
- }
33
- //#endregion
34
- //#region Helper Functions
35
- export function createLayerStateStore(diagnostic) {
36
- const states = new Map();
37
- return {
38
- get(executionId, layerId) {
39
- return frameworkCast(states.get(executionId)?.get(layerId));
40
- },
41
- set(executionId, layerId, state) {
42
- let execMap = states.get(executionId);
43
- if (!execMap) {
44
- execMap = new Map();
45
- states.set(executionId, execMap);
46
- }
47
- execMap.set(layerId, state);
48
- },
49
- cleanup(executionId) {
50
- states.delete(executionId);
51
- },
52
- diagnostic: diagnostic ?? (() => { }),
53
- };
54
- }
55
- async function withTimeout(promise, ms) {
56
- if (ms <= 0) {
57
- return promise;
58
- }
59
- let timer;
60
- return Promise.race([
61
- promise.finally(() => clearTimeout(timer)),
62
- new Promise((_, reject) => {
63
- timer = setTimeout(() => reject(new Error(`Timeout after ${ms}ms`)), ms);
64
- }),
65
- ]);
66
- }
67
- export function mostRestrictive(decisions) {
68
- let result = {
69
- action: SteeringAction.Allow,
70
- };
71
- const guidances = [];
72
- for (const d of decisions) {
73
- if (d.action === SteeringAction.Deny) {
74
- return d;
75
- }
76
- if (d.action === SteeringAction.Guide) {
77
- result = d;
78
- if (d.guidance) {
79
- guidances.push(d.guidance);
80
- }
81
- }
82
- }
83
- if (result.action === SteeringAction.Guide && guidances.length > 1) {
84
- return {
85
- action: SteeringAction.Guide,
86
- guidance: guidances.join('\n'),
87
- };
88
- }
89
- return result;
90
- }
91
- function layerItemSchemas(layer, base = defaultItemSchemaRegistry) {
92
- return base.extend(layer.itemSchemas);
93
- }
94
- //#endregion
95
- //#region Public API
96
- export async function initLayers({ layers, ctx, storage, store }) {
97
- // Sequential, array order
98
- for (const layer of layers) {
99
- if (!layer.hooks.init) {
100
- continue;
101
- }
102
- const scopeKey = resolveScopeKey(layer.scope, ctx);
103
- const scopedStorage = createScopedStorage(storage, layer.id, scopeKey);
104
- try {
105
- const timeout = layer.timeouts?.init ?? 1e4;
106
- const result = await withTimeout(layer.hooks.init({
107
- storage: scopedStorage,
108
- scopeKey,
109
- ctx,
110
- }), timeout);
111
- store.set(ctx.executionId, layer.id, result.state);
112
- }
113
- catch (e) {
114
- store.diagnostic(layer.id, 'init', e);
115
- }
116
- }
117
- }
118
- export async function recallLayers({ layers, query, ctx, log, budgets, store, itemSchemas = defaultItemSchemaRegistry, }) {
119
- const sorted = [
120
- ...layers,
121
- ].sort((a, b) => a.slot - b.slot);
122
- const results = [];
123
- for (const layer of sorted) {
124
- if (!layer.hooks.recall) {
125
- continue;
126
- }
127
- const state = store.get(ctx.executionId, layer.id);
128
- if (state === undefined && layer.hooks.init) {
129
- continue; // was disabled
130
- }
131
- const budget = budgets.get(layer.id) ?? 0;
132
- try {
133
- const timeout = layer.timeouts?.recall ?? 5e3;
134
- const result = await withTimeout(layer.hooks.recall({
135
- log,
136
- query,
137
- ctx,
138
- state,
139
- budget,
140
- }), timeout);
141
- if (!result) {
142
- continue;
143
- }
144
- const layerSchemas = layerItemSchemas(layer, itemSchemas);
145
- if (typeof result === 'string') {
146
- results.push({
147
- layerId: layer.id,
148
- items: [
149
- layerSchemas.parseWithCategory(createMessage(result, 'developer'), 'developerMessages'),
150
- ],
151
- tokenCount: estimateTokens(result),
152
- });
153
- continue;
154
- }
155
- results.push({
156
- layerId: layer.id,
157
- items: layerSchemas.parseMany(result.items),
158
- tokenCount: result.tokenCount,
159
- });
160
- if (result.state !== undefined) {
161
- store.set(ctx.executionId, layer.id, result.state);
162
- }
163
- }
164
- catch (e) {
165
- store.diagnostic(layer.id, 'recall', e);
166
- }
167
- }
168
- return results;
169
- }
170
- export async function storeLayers({ layers, response, ctx, log, store, storage, }) {
171
- // Concurrent via Promise.allSettled — each layer gets its own state snapshot
172
- const snapshots = [];
173
- for (const layer of layers) {
174
- if (!layer.hooks.store) {
175
- continue;
176
- }
177
- const state = store.get(ctx.executionId, layer.id);
178
- if (state === undefined && layer.hooks.init) {
179
- continue;
180
- }
181
- snapshots.push({
182
- layer,
183
- state,
184
- storeFn: layer.hooks.store,
185
- });
186
- }
187
- await Promise.allSettled(snapshots.map(async ({ layer, state, storeFn }) => {
188
- const timeout = layer.timeouts?.store ?? 3e4;
189
- try {
190
- const result = await withTimeout(storeFn({
191
- newItems: response.items,
192
- log,
193
- response,
194
- ctx,
195
- state,
196
- }), timeout);
197
- if (result?.state !== undefined) {
198
- store.set(ctx.executionId, layer.id, result.state);
199
- // Mirror to durable storage so the next execution's init() can
200
- // rehydrate. Skip 'execution' scope — its key rotates each run.
201
- if (layer.scope !== 'execution') {
202
- const scopedStorage = createScopedStorage(storage, layer.id, resolveScopeKey(layer.scope, ctx));
203
- try {
204
- await scopedStorage.set('state', result.state);
205
- }
206
- catch (persistErr) {
207
- store.diagnostic(layer.id, 'store', persistErr);
208
- }
209
- }
210
- }
211
- }
212
- catch (e) {
213
- store.diagnostic(layer.id, 'store', e);
214
- }
215
- }));
216
- }
217
- export async function disposeLayers({ layers, ctx, store }) {
218
- // Sequential, REVERSE array order
219
- const reversed = [
220
- ...layers,
221
- ].reverse();
222
- for (const layer of reversed) {
223
- if (!layer.hooks.dispose) {
224
- continue;
225
- }
226
- const state = store.get(ctx.executionId, layer.id);
227
- try {
228
- const timeout = layer.timeouts?.dispose ?? 5e3;
229
- await withTimeout(layer.hooks.dispose({
230
- state,
231
- }), timeout);
232
- }
233
- catch (e) {
234
- store.diagnostic(layer.id, 'dispose', e);
235
- }
236
- }
237
- store.cleanup(ctx.executionId);
238
- }
239
- export async function spawnLayers({ layers, parentCtx, childCtx, store, itemSchemas = defaultItemSchemaRegistry, }) {
240
- const results = [];
241
- const sorted = [
242
- ...layers,
243
- ].sort((a, b) => a.slot - b.slot);
244
- for (const layer of sorted) {
245
- if (!layer.hooks.onSpawn) {
246
- continue;
247
- }
248
- const parentState = store.get(parentCtx.executionId, layer.id);
249
- if (parentState === undefined) {
250
- continue;
251
- }
252
- try {
253
- const timeout = layer.timeouts?.onSpawn ?? 1e4;
254
- const result = await withTimeout(layer.hooks.onSpawn({
255
- parentState,
256
- childCtx,
257
- }), timeout);
258
- if (result && result.childState !== null) {
259
- store.set(childCtx.executionId, layer.id, result.childState);
260
- results.push({
261
- layerId: layer.id,
262
- childState: result.childState,
263
- items: layerItemSchemas(layer, itemSchemas).parseMany(result.items ?? []),
264
- });
265
- }
266
- }
267
- catch (e) {
268
- store.diagnostic(layer.id, 'onSpawn', e);
269
- }
270
- }
271
- return results;
272
- }
273
- export async function returnLayers({ layers, parentCtx, childCtx, childLog, result, store, }) {
274
- const sorted = [
275
- ...layers,
276
- ].sort((a, b) => a.slot - b.slot);
277
- let currentResult = result;
278
- for (const layer of sorted) {
279
- if (!layer.hooks.onReturn) {
280
- continue;
281
- }
282
- const childState = store.get(childCtx.executionId, layer.id);
283
- const parentState = store.get(parentCtx.executionId, layer.id);
284
- if (childState === undefined || parentState === undefined) {
285
- continue;
286
- }
287
- try {
288
- const timeout = layer.timeouts?.onReturn ?? 1e4;
289
- const returnResult = await withTimeout(layer.hooks.onReturn({
290
- childState,
291
- childLog,
292
- parentState,
293
- result: currentResult,
294
- }), timeout);
295
- if (returnResult?.parentState !== undefined) {
296
- store.set(parentCtx.executionId, layer.id, returnResult.parentState);
297
- }
298
- if (returnResult?.result !== undefined) {
299
- currentResult = returnResult.result;
300
- }
301
- }
302
- catch (e) {
303
- store.diagnostic(layer.id, 'onReturn', e);
304
- }
305
- }
306
- return frameworkCast(currentResult);
307
- }
308
- export async function completeLayers({ layers, ctx, log, outcome, store, }) {
309
- for (const layer of layers) {
310
- if (!layer.hooks.onComplete) {
311
- continue;
312
- }
313
- const state = store.get(ctx.executionId, layer.id);
314
- try {
315
- const timeout = layer.timeouts?.onComplete ?? 3e4;
316
- const result = await withTimeout(layer.hooks.onComplete({
317
- log,
318
- ctx,
319
- state,
320
- outcome,
321
- }), timeout);
322
- if (result && 'state' in result) {
323
- store.set(ctx.executionId, layer.id, result.state);
324
- }
325
- }
326
- catch (e) {
327
- store.diagnostic(layer.id, 'onComplete', e);
328
- }
329
- }
330
- }
331
- export async function beforeToolCallLayers({ layers, toolName, toolArgs, ctx, store, }) {
332
- const sorted = [
333
- ...layers,
334
- ].sort((a, b) => a.slot - b.slot);
335
- const decisions = [];
336
- for (const layer of sorted) {
337
- if (!layer.hooks.beforeToolCall) {
338
- continue;
339
- }
340
- const state = store.get(ctx.executionId, layer.id);
341
- if (state === undefined && layer.hooks.init) {
342
- continue;
343
- }
344
- try {
345
- const timeout = layer.timeouts?.beforeToolCall ?? 5e3;
346
- const result = await withTimeout(layer.hooks.beforeToolCall({
347
- toolName,
348
- toolArgs,
349
- ctx,
350
- state,
351
- }), timeout);
352
- if (result.state !== undefined) {
353
- store.set(ctx.executionId, layer.id, result.state);
354
- }
355
- if (result.decision.action === SteeringAction.Deny) {
356
- return result.decision;
357
- }
358
- decisions.push(result.decision);
359
- }
360
- catch (e) {
361
- if (e instanceof NoeticConfigError) {
362
- throw e;
363
- }
364
- store.diagnostic(layer.id, 'beforeToolCall', e);
365
- }
366
- }
367
- return mostRestrictive(decisions);
368
- }
369
- export async function afterModelCallLayers({ layers, response, ctx, store, }) {
370
- const sorted = [
371
- ...layers,
372
- ].sort((a, b) => a.slot - b.slot);
373
- const decisions = [];
374
- for (const layer of sorted) {
375
- if (!layer.hooks.afterModelCall) {
376
- continue;
377
- }
378
- const state = store.get(ctx.executionId, layer.id);
379
- if (state === undefined && layer.hooks.init) {
380
- continue;
381
- }
382
- try {
383
- const timeout = layer.timeouts?.afterModelCall ?? 1e4;
384
- const result = await withTimeout(layer.hooks.afterModelCall({
385
- response,
386
- ctx,
387
- state,
388
- }), timeout);
389
- if (result.state !== undefined) {
390
- store.set(ctx.executionId, layer.id, result.state);
391
- }
392
- if (result.decision.action === SteeringAction.Deny) {
393
- return result.decision;
394
- }
395
- decisions.push(result.decision);
396
- }
397
- catch (e) {
398
- if (e instanceof NoeticConfigError) {
399
- throw e;
400
- }
401
- store.diagnostic(layer.id, 'afterModelCall', e);
402
- }
403
- }
404
- return mostRestrictive(decisions);
405
- }
406
- /**
407
- * Run history items through every layer's `projectHistory` hook in slot order.
408
- * Each layer receives the previous layer's output. Storage (`itemLog`) is
409
- * never mutated — this is a pure projection over the input array. Returns
410
- * the projected items unchanged when no layer registers the hook.
411
- */
412
- export async function projectHistoryLayers({ layers, items, ctx, store, }) {
413
- const sorted = [
414
- ...layers,
415
- ].sort((a, b) => a.slot - b.slot);
416
- let current = items;
417
- for (const layer of sorted) {
418
- if (!layer.hooks.projectHistory) {
419
- continue;
420
- }
421
- const state = store.get(ctx.executionId, layer.id);
422
- if (state === undefined && layer.hooks.init) {
423
- continue;
424
- }
425
- try {
426
- const timeout = layer.timeouts?.projectHistory ?? 5e3;
427
- const result = await withTimeout(layer.hooks.projectHistory({
428
- items: current,
429
- ctx,
430
- state,
431
- }), timeout);
432
- current = result.items;
433
- }
434
- catch (e) {
435
- store.diagnostic(layer.id, 'projectHistory', e);
436
- }
437
- }
438
- return current;
439
- }
440
- const DEFAULT_ON_ITEM_APPEND_TIMEOUT = 5e3;
441
- /**
442
- * Run items through the onItemAppend pipeline.
443
- * Each layer can filter, transform, or inject items.
444
- * Returns final items to append and any re-render requests.
445
- */
446
- export async function runAppendPipeline({ layers, items, ctx, log, store, }) {
447
- const requests = [];
448
- let currentItems = items;
449
- // Run pipeline in slot order
450
- const sorted = [
451
- ...layers,
452
- ].sort((a, b) => a.slot - b.slot);
453
- for (const layer of sorted) {
454
- if (!layer.hooks.onItemAppend) {
455
- continue;
456
- }
457
- // Skip if no items left (all filtered by previous layer)
458
- if (currentItems.length === 0) {
459
- break;
460
- }
461
- const state = store.get(ctx.executionId, layer.id);
462
- // Skip if layer was disabled (has init but no state)
463
- if (state === undefined && layer.hooks.init) {
464
- continue;
465
- }
466
- try {
467
- const timeout = layer.timeouts?.onItemAppend ?? DEFAULT_ON_ITEM_APPEND_TIMEOUT;
468
- const result = await withTimeout(layer.hooks.onItemAppend({
469
- items: currentItems,
470
- log,
471
- ctx,
472
- state,
473
- }), timeout);
474
- // Update items for next layer in pipeline
475
- currentItems = result.items;
476
- // Update state if provided
477
- if (result.state !== undefined) {
478
- store.set(ctx.executionId, layer.id, result.state);
479
- }
480
- // Collect re-render request if present
481
- if (result.rerender) {
482
- requests.push({
483
- layerId: layer.id,
484
- slot: layer.slot,
485
- timing: result.timing ?? layer.rerenderTiming ?? 'batched',
486
- scope: result.scope ?? 'slot-after',
487
- });
488
- }
489
- }
490
- catch (e) {
491
- store.diagnostic(layer.id, 'onItemAppend', e);
492
- // On error, pass through items unchanged for this layer
493
- }
494
- }
495
- return {
496
- items: currentItems,
497
- rerenderRequests: requests,
498
- };
499
- }
500
- /**
501
- * Execute re-render based on collected requests.
502
- * Determines which layers need re-recall based on scope and runs them.
503
- * Returns new recall results to merge into view.
504
- */
505
- export async function executeRerender({ requests, layers, ctx, log, budgets, store, itemSchemas, query = '', depth = 0, }) {
506
- if (requests.length === 0) {
507
- return [];
508
- }
509
- // Prevent infinite re-render loops
510
- if (depth >= MAX_RERENDER_DEPTH) {
511
- // Log warning and return empty - don't throw to avoid breaking the flow
512
- console.warn(`[noetic] Re-render depth exceeded (${depth} >= ${MAX_RERENDER_DEPTH}). ` +
513
- 'Possible infinite re-render loop detected. Stopping re-render cascade.');
514
- return [];
515
- }
516
- // Determine which layers need re-recall based on scope
517
- const layersToRecall = new Set();
518
- for (const req of requests) {
519
- switch (req.scope) {
520
- case 'self':
521
- layersToRecall.add(req.layerId);
522
- break;
523
- case 'slot-after':
524
- for (const layer of layers) {
525
- if (layer.slot >= req.slot) {
526
- layersToRecall.add(layer.id);
527
- }
528
- }
529
- break;
530
- case 'all':
531
- for (const layer of layers) {
532
- layersToRecall.add(layer.id);
533
- }
534
- break;
535
- }
536
- }
537
- // Re-run recall for affected layers
538
- const affectedLayers = layers
539
- .filter((l) => layersToRecall.has(l.id))
540
- .sort((a, b) => a.slot - b.slot);
541
- // Use existing recallLayers with filtered layers
542
- return recallLayers({
543
- layers: affectedLayers,
544
- query,
545
- ctx,
546
- log,
547
- budgets,
548
- store,
549
- itemSchemas,
550
- });
551
- }
552
- //#endregion
@@ -1,32 +0,0 @@
1
- import type { ZodType } from 'zod';
2
- import type { ExecutionContext, LayerDataDecl, LayerFunctionDecl } from '../types/memory.js';
3
- /**
4
- * Creates a read-only data declaration for a memory layer's `provides` map.
5
- *
6
- * @public
7
- * @param opts.read - Function that projects a value from the layer's current state.
8
- * @returns A `LayerDataDecl` to include in a layer's `provides`.
9
- */
10
- export declare function layerData<T, TState>(opts: {
11
- read: (state: TState) => T;
12
- }): LayerDataDecl<T, TState>;
13
- /**
14
- * Creates a callable function declaration for a memory layer's `provides` map.
15
- * Functions are accessible via `ctx.memory['layerId'].fn()` and automatically exposed as LLM tools.
16
- *
17
- * @public
18
- * @param opts.description - Human-readable description used as tool description for LLM.
19
- * @param opts.input - Zod schema validating input arguments.
20
- * @param opts.output - Zod schema validating the return value.
21
- * @param opts.execute - Async function receiving args, current state, and execution context.
22
- * @returns A `LayerFunctionDecl` to include in a layer's `provides`.
23
- */
24
- export declare function layerFn<TInput, TOutput, TState>(opts: {
25
- description: string;
26
- input: ZodType<TInput>;
27
- output: ZodType<TOutput>;
28
- execute: (args: TInput, state: TState, ctx: ExecutionContext) => Promise<{
29
- result: TOutput;
30
- state?: TState;
31
- }>;
32
- }): LayerFunctionDecl<TInput, TOutput, TState>;
@@ -1,33 +0,0 @@
1
- /**
2
- * Creates a read-only data declaration for a memory layer's `provides` map.
3
- *
4
- * @public
5
- * @param opts.read - Function that projects a value from the layer's current state.
6
- * @returns A `LayerDataDecl` to include in a layer's `provides`.
7
- */
8
- export function layerData(opts) {
9
- return {
10
- kind: 'data',
11
- read: opts.read,
12
- };
13
- }
14
- /**
15
- * Creates a callable function declaration for a memory layer's `provides` map.
16
- * Functions are accessible via `ctx.memory['layerId'].fn()` and automatically exposed as LLM tools.
17
- *
18
- * @public
19
- * @param opts.description - Human-readable description used as tool description for LLM.
20
- * @param opts.input - Zod schema validating input arguments.
21
- * @param opts.output - Zod schema validating the return value.
22
- * @param opts.execute - Async function receiving args, current state, and execution context.
23
- * @returns A `LayerFunctionDecl` to include in a layer's `provides`.
24
- */
25
- export function layerFn(opts) {
26
- return {
27
- kind: 'function',
28
- description: opts.description,
29
- input: opts.input,
30
- output: opts.output,
31
- execute: opts.execute,
32
- };
33
- }
@@ -1,16 +0,0 @@
1
- import type { Context } from '../types/context.js';
2
- import type { LastLayerUsage } from '../types/context-parts/layer-usage.js';
3
- import type { RecallLayerOutput } from '../types/runtime.js';
4
- import type { Tool } from '../types/tool.js';
5
- interface ComputeLayerUsageParams {
6
- ctx: Context;
7
- modelId: string;
8
- instructions?: string;
9
- tools?: ReadonlyArray<Tool>;
10
- /** Per-layer recall output assembled into the context view for this LLM call. */
11
- recallResults: ReadonlyArray<RecallLayerOutput>;
12
- }
13
- export declare function computeLayerUsage({ ctx, modelId, instructions, tools, recallResults, }: ComputeLayerUsageParams): LastLayerUsage;
14
- /** Commit computed usage to the Context, replacing any prior snapshot. */
15
- export declare function commitLayerUsage(ctx: Context, usage: LastLayerUsage): void;
16
- export {};
@@ -1,54 +0,0 @@
1
- import { estimateTokens } from '../util/message-helpers.js';
2
- function canWriteLayerUsage(ctx) {
3
- const desc = Object.getOwnPropertyDescriptor(ctx, 'lastLayerUsage');
4
- if (desc === undefined) {
5
- return false;
6
- }
7
- return desc.writable !== false;
8
- }
9
- //#endregion
10
- //#region Helpers
11
- function estimateJsonTokens(value) {
12
- try {
13
- return estimateTokens(JSON.stringify(value));
14
- }
15
- catch {
16
- return 0;
17
- }
18
- }
19
- //#endregion
20
- //#region Public API
21
- export function computeLayerUsage({ ctx, modelId, instructions, tools, recallResults, }) {
22
- const layers = recallResults
23
- .map((r) => ({
24
- layerId: r.layerId,
25
- tokenCount: r.tokenCount,
26
- items: r.items,
27
- }))
28
- .sort((a, b) => a.layerId.localeCompare(b.layerId));
29
- let historyTokens = 0;
30
- for (const item of ctx.itemLog.items) {
31
- historyTokens += estimateJsonTokens(item);
32
- }
33
- const systemPromptTokens = instructions ? estimateTokens(instructions) : 0;
34
- const toolsTokens = tools && tools.length > 0 ? estimateJsonTokens(tools) : 0;
35
- const layerTotal = layers.reduce((sum, l) => sum + l.tokenCount, 0);
36
- const totalUsedTokens = systemPromptTokens + toolsTokens + historyTokens + layerTotal;
37
- return {
38
- executionId: ctx.id,
39
- modelId,
40
- layers,
41
- systemPromptTokens,
42
- toolsTokens,
43
- historyTokens,
44
- totalUsedTokens,
45
- };
46
- }
47
- /** Commit computed usage to the Context, replacing any prior snapshot. */
48
- export function commitLayerUsage(ctx, usage) {
49
- if (!canWriteLayerUsage(ctx)) {
50
- return;
51
- }
52
- ctx.lastLayerUsage = usage;
53
- }
54
- //#endregion