@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.
- package/dist/adapters/in-memory-fs-adapter.d.ts +1 -1
- package/dist/adapters/in-memory-fs-adapter.js +1 -1
- package/dist/adapters/in-memory-shell-adapter.d.ts +1 -1
- package/dist/adapters/in-memory-subprocess/manifest-persistence.d.ts +2 -2
- package/dist/adapters/in-memory-subprocess/metadata.d.ts +1 -1
- package/dist/adapters/in-memory-subprocess/types.d.ts +2 -2
- package/dist/adapters/in-memory-subprocess-adapter.d.ts +1 -1
- package/dist/adapters/openrouter.d.ts +2 -6
- package/dist/adapters/openrouter.js +1 -4
- package/dist/builders/channel-builder.d.ts +1 -1
- package/dist/builders/control-flow-builders.d.ts +2 -3
- package/dist/builders/control-flow-builders.js +1 -2
- package/dist/builders/every.d.ts +2 -3
- package/dist/builders/every.js +1 -1
- package/dist/builders/layer-provides-builders.d.ts +1 -1
- package/dist/builders/layer-provides-builders.js +1 -1
- package/dist/builders/loop-builder.d.ts +2 -2
- package/dist/builders/loop-builder.js +1 -1
- package/dist/builders/memory-builder.d.ts +1 -1
- package/dist/builders/memory-builder.js +1 -1
- package/dist/builders/provide-builder.d.ts +2 -2
- package/dist/builders/provide-builder.js +1 -1
- package/dist/builders/spawn-builder.d.ts +2 -3
- package/dist/builders/spawn-builder.js +1 -1
- package/dist/builders/step-builders.d.ts +2 -6
- package/dist/builders/step-builders.js +1 -1
- package/dist/builders/tool-builder.d.ts +1 -3
- package/dist/builders/tool-builder.js +1 -1
- package/dist/builders/workflow-hydrator.d.ts +2 -3
- package/dist/builders/workflow-hydrator.js +1 -2
- package/dist/conditions/conditions.d.ts +2 -3
- package/dist/conditions/conditions.js +1 -1
- package/dist/harness/agent-harness.d.ts +15 -5
- package/dist/harness/agent-harness.js +65 -10
- package/dist/harness/deps/memory.d.ts +2 -5
- package/dist/harness/deps/memory.js +1 -4
- package/dist/harness/deps/types.d.ts +3 -16
- package/dist/harness/deps/types.js +1 -1
- package/dist/harness/model-call.d.ts +1 -3
- package/dist/harness/model-call.js +10 -10
- package/dist/harness/model-schema.d.ts +10 -4
- package/dist/harness/model-schema.js +9 -1
- package/dist/index.d.ts +28 -49
- package/dist/index.js +9 -27
- package/dist/interpreter/action-deps.d.ts +4 -8
- package/dist/interpreter/action-deps.js +2 -6
- package/dist/interpreter/action-types.d.ts +3 -8
- package/dist/interpreter/action-types.js +1 -1
- package/dist/interpreter/collect-tools.d.ts +1 -2
- package/dist/interpreter/collect-tools.js +1 -1
- package/dist/interpreter/execute-action.js +122 -27
- package/dist/interpreter/execute-control.d.ts +1 -2
- package/dist/interpreter/execute-control.js +60 -7
- package/dist/interpreter/execute.d.ts +2 -3
- package/dist/interpreter/execute.js +1 -2
- package/dist/interpreter/message-helpers.d.ts +1 -1
- package/dist/interpreter/message-helpers.js +1 -1
- package/dist/interpreter/step-dispatcher.d.ts +2 -5
- package/dist/interpreter/typeguards.d.ts +3 -4
- package/dist/interpreter/typeguards.js +1 -1
- package/dist/observability/span-impl.d.ts +1 -1
- package/dist/observability/trace-exporter.d.ts +1 -1
- package/dist/patterns/dynamic-workflow.d.ts +2 -5
- package/dist/patterns/dynamic-workflow.js +1 -2
- package/dist/patterns/flow.d.ts +2 -2
- package/dist/patterns/flow.js +1 -1
- package/dist/patterns/interview.d.ts +2 -2
- package/dist/patterns/interview.js +1 -1
- package/dist/patterns/plans.d.ts +2 -3
- package/dist/patterns/plans.js +1 -1
- package/dist/patterns/ralph-wiggum.d.ts +2 -3
- package/dist/patterns/react.d.ts +2 -3
- package/dist/portable/memory-layers.d.ts +1 -7
- package/dist/portable/memory-layers.js +1 -7
- package/dist/portable.d.ts +2 -2
- package/dist/portable.js +2 -2
- package/dist/runtime/broadcaster-utils.d.ts +1 -1
- package/dist/runtime/channel-store.d.ts +43 -3
- package/dist/runtime/channel-store.js +233 -37
- package/dist/runtime/context-deps.d.ts +3 -3
- package/dist/runtime/context-deps.js +2 -2
- package/dist/runtime/context-impl.d.ts +17 -1
- package/dist/runtime/context-impl.js +30 -3
- package/dist/runtime/context-type-deps.d.ts +2 -11
- package/dist/runtime/cwd-helpers.d.ts +1 -1
- package/dist/runtime/detached-handle.d.ts +2 -3
- package/dist/runtime/detached-handle.js +1 -3
- package/dist/runtime/durable/checkpoint-store.d.ts +1 -1
- package/dist/runtime/durable/checkpoint-store.js +1 -1
- package/dist/runtime/durable/harness-checkpoints.d.ts +2 -5
- package/dist/runtime/durable/runnable-loop.d.ts +1 -3
- package/dist/runtime/durable/session-seed.d.ts +1 -1
- package/dist/runtime/durable/stall-nudge.d.ts +17 -10
- package/dist/runtime/durable/stall-nudge.js +29 -10
- package/dist/runtime/event-broadcaster.d.ts +10 -2
- package/dist/runtime/event-broadcaster.js +43 -19
- package/dist/runtime/in-memory-storage.d.ts +1 -1
- package/dist/runtime/in-memory-storage.js +1 -1
- package/dist/runtime/item-log-impl.d.ts +1 -3
- package/dist/runtime/item-log-impl.js +1 -1
- package/dist/runtime/message-queue.d.ts +1 -2
- package/dist/runtime/session-runner.d.ts +1 -4
- package/dist/runtime/session-streams.d.ts +1 -2
- package/dist/runtime/session-streams.js +1 -1
- package/dist/runtime/step-registry.d.ts +2 -2
- package/dist/runtime/step-registry.js +1 -2
- package/dist/runtime/tool-memory.d.ts +1 -3
- package/dist/types/mutable-context.d.ts +2 -3
- package/dist/types/step-registrar.d.ts +1 -1
- package/dist/unstable.d.ts +5 -9
- package/dist/unstable.js +3 -6
- package/dist/until/combinators.d.ts +1 -1
- package/dist/until/never.d.ts +1 -1
- package/dist/until/predicates.d.ts +2 -2
- package/package.json +4 -2
- package/dist/errors/noetic-config-error.d.ts +0 -41
- package/dist/errors/noetic-config-error.js +0 -44
- package/dist/errors/noetic-error.d.ts +0 -18
- package/dist/errors/noetic-error.js +0 -54
- package/dist/memory/budget.d.ts +0 -23
- package/dist/memory/budget.js +0 -117
- package/dist/memory/exec-context-factory.d.ts +0 -25
- package/dist/memory/exec-context-factory.js +0 -30
- package/dist/memory/flow-schema.d.ts +0 -52
- package/dist/memory/flow-schema.js +0 -102
- package/dist/memory/function-call-utils.d.ts +0 -6
- package/dist/memory/function-call-utils.js +0 -27
- package/dist/memory/layer-api.d.ts +0 -14
- package/dist/memory/layer-api.js +0 -91
- package/dist/memory/layer-lifecycle.d.ts +0 -160
- package/dist/memory/layer-lifecycle.js +0 -552
- package/dist/memory/layer-provides.d.ts +0 -32
- package/dist/memory/layer-provides.js +0 -33
- package/dist/memory/layer-usage.d.ts +0 -16
- package/dist/memory/layer-usage.js +0 -54
- package/dist/memory/layers/durable-task-state.d.ts +0 -79
- package/dist/memory/layers/durable-task-state.js +0 -118
- package/dist/memory/layers/file-reference.d.ts +0 -55
- package/dist/memory/layers/file-reference.js +0 -594
- package/dist/memory/layers/history-window.d.ts +0 -29
- package/dist/memory/layers/history-window.js +0 -114
- package/dist/memory/layers/observational-memory.d.ts +0 -53
- package/dist/memory/layers/observational-memory.js +0 -109
- package/dist/memory/layers/plan.d.ts +0 -55
- package/dist/memory/layers/plan.js +0 -374
- package/dist/memory/layers/static-content.d.ts +0 -27
- package/dist/memory/layers/static-content.js +0 -35
- package/dist/memory/layers/steering.d.ts +0 -51
- package/dist/memory/layers/steering.js +0 -258
- package/dist/memory/layers/temporal.d.ts +0 -91
- package/dist/memory/layers/temporal.js +0 -245
- package/dist/memory/layers/tool-memory-layer.d.ts +0 -16
- package/dist/memory/layers/tool-memory-layer.js +0 -43
- package/dist/memory/layers/working-memory.d.ts +0 -44
- package/dist/memory/layers/working-memory.js +0 -92
- package/dist/memory/projector.d.ts +0 -10
- package/dist/memory/projector.js +0 -19
- package/dist/memory/scope.d.ts +0 -3
- package/dist/memory/scope.js +0 -31
- package/dist/memory/strip-unresolved.d.ts +0 -13
- package/dist/memory/strip-unresolved.js +0 -35
- package/dist/schemas/item.d.ts +0 -35
- package/dist/schemas/item.js +0 -155
- package/dist/types/channel.d.ts +0 -29
- package/dist/types/channel.js +0 -1
- package/dist/types/common.d.ts +0 -68
- package/dist/types/common.js +0 -1
- package/dist/types/context-parts/item-log.d.ts +0 -6
- package/dist/types/context-parts/item-log.js +0 -1
- package/dist/types/context-parts/layer-usage.d.ts +0 -18
- package/dist/types/context-parts/layer-usage.js +0 -1
- package/dist/types/context.d.ts +0 -202
- package/dist/types/context.js +0 -1
- package/dist/types/detached.d.ts +0 -17
- package/dist/types/detached.js +0 -7
- package/dist/types/error.d.ts +0 -66
- package/dist/types/error.js +0 -1
- package/dist/types/fs-adapter.d.ts +0 -51
- package/dist/types/fs-adapter.js +0 -3
- package/dist/types/harness-result.d.ts +0 -43
- package/dist/types/harness-result.js +0 -2
- package/dist/types/items.d.ts +0 -131
- package/dist/types/items.js +0 -2
- package/dist/types/memory-context.d.ts +0 -39
- package/dist/types/memory-context.js +0 -1
- package/dist/types/memory.d.ts +0 -306
- package/dist/types/memory.js +0 -13
- package/dist/types/observability.d.ts +0 -30
- package/dist/types/observability.js +0 -1
- package/dist/types/runtime.d.ts +0 -256
- package/dist/types/runtime.js +0 -1
- package/dist/types/shell-adapter.d.ts +0 -34
- package/dist/types/shell-adapter.js +0 -10
- package/dist/types/steering.d.ts +0 -89
- package/dist/types/steering.js +0 -14
- package/dist/types/step.d.ts +0 -231
- package/dist/types/step.js +0 -1
- package/dist/types/subprocess-adapter.d.ts +0 -157
- package/dist/types/subprocess-adapter.js +0 -3
- package/dist/types/tool-context.d.ts +0 -34
- package/dist/types/tool-context.js +0 -1
- package/dist/types/tool.d.ts +0 -64
- package/dist/types/tool.js +0 -1
- package/dist/util/framework-cast.d.ts +0 -10
- package/dist/util/framework-cast.js +0 -16
- package/dist/util/message-helpers.d.ts +0 -17
- 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
|