@noetic-tools/core 5.5.0 → 5.7.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/builders/control-flow-builders.d.ts +6 -4
- package/dist/builders/control-flow-builders.js +3 -2
- package/dist/builders/decide-builders.d.ts +86 -0
- package/dist/builders/decide-builders.js +230 -0
- package/dist/builders/dynamic-workflow.js +1 -0
- package/dist/builders/workflow-hydrator.js +81 -2
- package/dist/conditions/conditions.d.ts +9 -3
- package/dist/conditions/conditions.js +84 -25
- package/dist/harness/agent-harness.d.ts +18 -3
- package/dist/harness/agent-harness.js +63 -6
- package/dist/harness/decide-call.d.ts +19 -0
- package/dist/harness/decide-call.js +483 -0
- package/dist/harness/deps/adapters.d.ts +1 -0
- package/dist/harness/deps/adapters.js +1 -0
- package/dist/harness/deps/context.d.ts +1 -1
- package/dist/harness/deps/context.js +1 -1
- package/dist/harness/deps/types.d.ts +1 -1
- package/dist/index.d.ts +14 -6
- package/dist/index.js +6 -2
- package/dist/interpreter/action-deps.d.ts +1 -1
- package/dist/interpreter/action-deps.js +1 -1
- package/dist/interpreter/action-types.d.ts +1 -1
- package/dist/interpreter/collect-tools.js +2 -0
- package/dist/interpreter/execute-action.js +3 -20
- package/dist/interpreter/execute-control.js +1 -1
- package/dist/interpreter/execute-decide.d.ts +10 -0
- package/dist/interpreter/execute-decide.js +417 -0
- package/dist/interpreter/execute.js +8 -3
- package/dist/observability/genai-attributes.d.ts +6 -0
- package/dist/observability/genai-attributes.js +6 -0
- package/dist/portable/context-layers.d.ts +1 -1
- package/dist/portable/context-layers.js +1 -1
- package/dist/runtime/context-impl.d.ts +3 -0
- package/dist/runtime/context-impl.js +2 -0
- package/dist/schemas/workflow.d.ts +1 -1
- package/dist/util/status-code.d.ts +2 -0
- package/dist/util/status-code.js +7 -0
- package/package.json +7 -6
- package/schema/noetic-workflow.schema.json +396 -0
|
@@ -3,7 +3,7 @@ import { AcpSessionStore } from '../runtime/acp-session-store.js';
|
|
|
3
3
|
import type { LayerStateStore, RecallCache } from './deps/context.js';
|
|
4
4
|
import type { DetachedSpawnOverrides } from './deps/interpreter.js';
|
|
5
5
|
import type { CheckpointStore, EventBroadcaster, RestoreCheckpointOptions, StepLedgerRetention, StepLedgerStore } from './deps/runtime.js';
|
|
6
|
-
import type { AcpLiveSession, AcpSessionInfo, AgentConfig, AgentHarnessContract, AgentHooks, CallModelRequest, Channel, ChannelHandle, Context, ContextCacheConfig, ContextCacheStore, ContextData, ContextLayer, CwdState, DeliveryMode, DetachedHandle, ExecuteInput, ExecuteOptions, ExternalChannel, FsAdapter, HarnessResponse, HarnessStatus, Item, ItemSchemaConfig, LLMResponse, LlmProviderConfig, ProjectionPolicy, RecallLayerOutput, SessionScope, SessionUsage, ShellAdapter, Span, SteeringDecision, Step, StorageAdapter, StreamEvent, StreamingItem, SubprocessAdapter, Tool, TraceExporter, ZodType } from './deps/types.js';
|
|
6
|
+
import type { AcpLiveSession, AcpSessionInfo, AgentConfig, AgentHarnessContract, AgentHooks, CallModelRequest, Channel, ChannelHandle, Context, ContextCacheConfig, ContextCacheStore, ContextData, ContextLayer, CwdState, DecideRequest, DecideResponse, DecisionRecord, DeliveryMode, DetachedHandle, ExecuteInput, ExecuteOptions, ExternalChannel, FsAdapter, HarnessResponse, HarnessStatus, Item, ItemSchemaConfig, LLMResponse, LlmProviderConfig, ProjectionPolicy, RecallLayerOutput, RecallOptions, SessionScope, SessionUsage, ShellAdapter, Span, SteeringDecision, Step, StorageAdapter, StreamEvent, StreamingItem, SubprocessAdapter, Tool, TraceExporter, ZodType } from './deps/types.js';
|
|
7
7
|
export { createStreamIdleWatchdog } from './model-call.js';
|
|
8
8
|
/**
|
|
9
9
|
* Storage-scoped environment configuration for `AgentHarness`.
|
|
@@ -87,8 +87,12 @@ interface AgentHarnessOpts<TParams extends Record<string, unknown> = Record<stri
|
|
|
87
87
|
* those produced by spawn/fork. Defaults to `process.cwd()`.
|
|
88
88
|
*/
|
|
89
89
|
initialCwd?: string;
|
|
90
|
+
/** Default model for `decide` steps. */
|
|
91
|
+
decisionModel?: string;
|
|
90
92
|
/** @internal Test-only escape hatch to inject a mock callModel implementation. */
|
|
91
93
|
_testCallModel?: (request: CallModelRequest) => Promise<LLMResponse>;
|
|
94
|
+
/** @internal Test-only escape hatch to inject a mock decide implementation. */
|
|
95
|
+
_testDecide?: (request: DecideRequest) => Promise<DecideResponse>;
|
|
92
96
|
}
|
|
93
97
|
/** Env vars consulted when resolving the LLM client (read defensively so the
|
|
94
98
|
* harness also works in runtimes without a `process` global, e.g. the browser). */
|
|
@@ -154,6 +158,11 @@ export declare class AgentHarness<TParams extends Record<string, unknown> = Reco
|
|
|
154
158
|
* without friend-class gymnastics. Do not access from outside core. */
|
|
155
159
|
readonly _contextLayers?: ContextLayer[];
|
|
156
160
|
private readonly client?;
|
|
161
|
+
/** SDK 1.x client for the decisions endpoint; the agent's client predates it. */
|
|
162
|
+
private readonly decisionsClient?;
|
|
163
|
+
private readonly decideOverride?;
|
|
164
|
+
/** Model id → whether it answers natively as a decision model. */
|
|
165
|
+
private readonly decisionModels;
|
|
157
166
|
private readonly channelStore;
|
|
158
167
|
/** Re-entrant `run()` depth per root context id — see `executeClosingChannels`. */
|
|
159
168
|
private readonly rootRunDepth;
|
|
@@ -207,6 +216,8 @@ export declare class AgentHarness<TParams extends Record<string, unknown> = Reco
|
|
|
207
216
|
* `ctx.id` (the layer-state store's executionId).
|
|
208
217
|
*/
|
|
209
218
|
private readonly initializedExecutions;
|
|
219
|
+
/** Executions restored from a checkpoint: their first layer init keeps the restored state. */
|
|
220
|
+
private readonly restoredExecutions;
|
|
210
221
|
readonly traceExporter: TraceExporter;
|
|
211
222
|
/**
|
|
212
223
|
* Long-lived shared cwd state. The same reference is seeded into every
|
|
@@ -242,6 +253,8 @@ export declare class AgentHarness<TParams extends Record<string, unknown> = Reco
|
|
|
242
253
|
private getOrCreateSession;
|
|
243
254
|
private requireSession;
|
|
244
255
|
callModel(request: CallModelRequest): Promise<LLMResponse>;
|
|
256
|
+
decide(request: DecideRequest): Promise<DecideResponse>;
|
|
257
|
+
notifyDecision(layers: ContextLayer[], record: DecisionRecord, ctx: Context): Promise<void>;
|
|
245
258
|
run<I, O>(s: Step<ContextData, I, O>, input: I, ctx: Context): Promise<O>;
|
|
246
259
|
/** Run all layer `init` hooks before the first step executes. Per spec 11,
|
|
247
260
|
* init MUST complete before any recall fires so layer state is populated. */
|
|
@@ -266,6 +279,8 @@ export declare class AgentHarness<TParams extends Record<string, unknown> = Reco
|
|
|
266
279
|
detachedSpawn<I, O>(s: Step<ContextData, I, O>, input: I, parentCtx: Context, overrides?: DetachedSpawnOverrides): DetachedHandle<O>;
|
|
267
280
|
createContext(opts?: {
|
|
268
281
|
parent?: Context;
|
|
282
|
+
/** Charge this context's usage to `parent` as it is spent. Default `true`. */
|
|
283
|
+
rollUpUsage?: boolean;
|
|
269
284
|
items?: Item[];
|
|
270
285
|
state?: unknown;
|
|
271
286
|
threadId?: string;
|
|
@@ -295,8 +310,8 @@ export declare class AgentHarness<TParams extends Record<string, unknown> = Reco
|
|
|
295
310
|
recallLayers(layers: ContextLayer[], input: string, ctx: Context): Promise<RecallLayerOutput[]>;
|
|
296
311
|
/** Allocate per-layer recall budgets from the harness projection policy. */
|
|
297
312
|
private layerBudgets;
|
|
298
|
-
recallLayersAtomic(layers: ContextLayer[], input: string, ctx: Context, budgets: Map<string, number
|
|
299
|
-
recallLayersEventual(layers: ContextLayer[], input: string, ctx: Context, budgets: Map<string, number
|
|
313
|
+
recallLayersAtomic(layers: ContextLayer[], input: string, ctx: Context, budgets: Map<string, number>, opts?: RecallOptions): Promise<RecallLayerOutput[]>;
|
|
314
|
+
recallLayersEventual(layers: ContextLayer[], input: string, ctx: Context, budgets: Map<string, number>, opts?: RecallOptions): Promise<RecallLayerOutput[]>;
|
|
300
315
|
/**
|
|
301
316
|
* Compute the items array that would be sent to the model on the next turn —
|
|
302
317
|
* the same arrangement `executeLLM` builds: harness-level context layers'
|
|
@@ -2,8 +2,9 @@ import { frameworkCast, ItemSchemaRegistry, NoeticConfigError } from '@noetic-to
|
|
|
2
2
|
import { SpanImpl } from '../observability/span-impl.js';
|
|
3
3
|
import { NoopExporter } from '../observability/trace-exporter.js';
|
|
4
4
|
import { AcpSessionStore } from '../runtime/acp-session-store.js';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { callDecide } from './decide-call.js';
|
|
6
|
+
import { createInMemoryFsAdapter, createInMemoryShellAdapter, createInMemorySubprocessAdapter, OpenRouter, OpenRouterSdk, } from './deps/adapters.js';
|
|
7
|
+
import { afterModelCallLayers, allocateBudgets, assembleView, beforeToolCallLayers, completeLayers, contextToExecCtx, createContextCacheStore, createLayerStateStore, createRecallCache, DEFAULT_PROJECTION, disposeLayers, executeRerender, initLayers, notifyDecision, projectHistoryLayers, recallLayers, recallLayersAtomic, recallLayersEventual, resolveLayerTools, runAppendPipeline, storeLayers, } from './deps/context.js';
|
|
7
8
|
import { collectAllTools, deduplicateTools, dispatchStepThroughAdapter, execute, prepareBandedView, } from './deps/interpreter.js';
|
|
8
9
|
import { buildItemStream, ChannelStore, ContextImpl, captureCheckpoint, clearCheckpoint, collectContextTree, createInMemoryStorage, createStepLedgerStore, filterReasoningStream, filterTextStream, resolveStepLedgerRetention, restoreFromCheckpoint, SessionRunner, StepLedger, snapshotCwdState, } from './deps/runtime.js';
|
|
9
10
|
import { SteeringAction } from './deps/types.js';
|
|
@@ -144,6 +145,16 @@ function createClient(config, contextCache) {
|
|
|
144
145
|
},
|
|
145
146
|
});
|
|
146
147
|
}
|
|
148
|
+
function createDecisionsClient(config) {
|
|
149
|
+
const resolved = resolveLlmClient(config, readLlmEnv());
|
|
150
|
+
if (!resolved) {
|
|
151
|
+
return undefined;
|
|
152
|
+
}
|
|
153
|
+
return new OpenRouterSdk({
|
|
154
|
+
apiKey: resolved.apiKey,
|
|
155
|
+
serverURL: resolved.serverURL,
|
|
156
|
+
});
|
|
157
|
+
}
|
|
147
158
|
//#region AgentHarness
|
|
148
159
|
/**
|
|
149
160
|
* Default agent harness for executing agent steps with built-in channel, context, and trace support.
|
|
@@ -186,6 +197,11 @@ export class AgentHarness {
|
|
|
186
197
|
* without friend-class gymnastics. Do not access from outside core. */
|
|
187
198
|
_contextLayers;
|
|
188
199
|
client;
|
|
200
|
+
/** SDK 1.x client for the decisions endpoint; the agent's client predates it. */
|
|
201
|
+
decisionsClient;
|
|
202
|
+
decideOverride;
|
|
203
|
+
/** Model id → whether it answers natively as a decision model. */
|
|
204
|
+
decisionModels = new Map();
|
|
189
205
|
channelStore;
|
|
190
206
|
/** Re-entrant `run()` depth per root context id — see `executeClosingChannels`. */
|
|
191
207
|
rootRunDepth = new Map();
|
|
@@ -252,6 +268,8 @@ export class AgentHarness {
|
|
|
252
268
|
* `ctx.id` (the layer-state store's executionId).
|
|
253
269
|
*/
|
|
254
270
|
initializedExecutions = new Set();
|
|
271
|
+
/** Executions restored from a checkpoint: their first layer init keeps the restored state. */
|
|
272
|
+
restoredExecutions = new Set();
|
|
255
273
|
traceExporter;
|
|
256
274
|
/**
|
|
257
275
|
* Long-lived shared cwd state. The same reference is seeded into every
|
|
@@ -276,6 +294,7 @@ export class AgentHarness {
|
|
|
276
294
|
projection: opts.projection,
|
|
277
295
|
forceAtomicRecall: opts.forceAtomicRecall,
|
|
278
296
|
contextCache: opts.contextCache,
|
|
297
|
+
decisionModel: opts.decisionModel,
|
|
279
298
|
};
|
|
280
299
|
this.fs = environment?.fs ?? createInMemoryFsAdapter();
|
|
281
300
|
this.shell = environment?.shell ?? createInMemoryShellAdapter();
|
|
@@ -294,6 +313,10 @@ export class AgentHarness {
|
|
|
294
313
|
this.client = opts._testCallModel
|
|
295
314
|
? undefined
|
|
296
315
|
: createClient(opts.callModelDefaults, opts.contextCache);
|
|
316
|
+
this.decideOverride = opts._testDecide;
|
|
317
|
+
this.decisionsClient = opts._testCallModel
|
|
318
|
+
? undefined
|
|
319
|
+
: createDecisionsClient(opts.callModelDefaults);
|
|
297
320
|
this.channelStore = new ChannelStore();
|
|
298
321
|
this.traceExporter = opts.traceExporter ?? new NoopExporter();
|
|
299
322
|
this.layerStateStore =
|
|
@@ -510,6 +533,27 @@ export class AgentHarness {
|
|
|
510
533
|
}).callModel(request);
|
|
511
534
|
}
|
|
512
535
|
//#endregion
|
|
536
|
+
//#region decide
|
|
537
|
+
async decide(request) {
|
|
538
|
+
if (this.decideOverride) {
|
|
539
|
+
return this.decideOverride(request);
|
|
540
|
+
}
|
|
541
|
+
return callDecide(request, {
|
|
542
|
+
client: this.decisionsClient,
|
|
543
|
+
callModel: (r) => this.callModel(r),
|
|
544
|
+
nativeModels: this.decisionModels,
|
|
545
|
+
});
|
|
546
|
+
}
|
|
547
|
+
async notifyDecision(layers, record, ctx) {
|
|
548
|
+
await notifyDecision({
|
|
549
|
+
layers,
|
|
550
|
+
record,
|
|
551
|
+
ctx: this.toExecCtx(ctx),
|
|
552
|
+
store: this.layerStateStore,
|
|
553
|
+
recallCache: this.recallCache,
|
|
554
|
+
});
|
|
555
|
+
}
|
|
556
|
+
//#endregion
|
|
513
557
|
async run(s, input, ctx) {
|
|
514
558
|
// Populate the unified tool pool when an embedder drives a step directly on
|
|
515
559
|
// a bare `createContext()` context (the turn pipeline does this per turn).
|
|
@@ -584,7 +628,14 @@ export class AgentHarness {
|
|
|
584
628
|
return;
|
|
585
629
|
}
|
|
586
630
|
this.initializedExecutions.add(ctx.id);
|
|
587
|
-
|
|
631
|
+
const keep = this.restoredExecutions.delete(ctx.id);
|
|
632
|
+
await initLayers({
|
|
633
|
+
layers,
|
|
634
|
+
ctx: this.toExecCtx(ctx),
|
|
635
|
+
storage,
|
|
636
|
+
store: this.layerStateStore,
|
|
637
|
+
keep,
|
|
638
|
+
});
|
|
588
639
|
}
|
|
589
640
|
detachedSpawn(s, input, parentCtx, overrides) {
|
|
590
641
|
/* NOT a checkpoint boundary, despite spec 23 listing one here: a DetachedHandle's
|
|
@@ -707,7 +758,7 @@ export class AgentHarness {
|
|
|
707
758
|
a.allocated,
|
|
708
759
|
]));
|
|
709
760
|
}
|
|
710
|
-
async recallLayersAtomic(layers, input, ctx, budgets) {
|
|
761
|
+
async recallLayersAtomic(layers, input, ctx, budgets, opts) {
|
|
711
762
|
return recallLayersAtomic({
|
|
712
763
|
layers,
|
|
713
764
|
query: input,
|
|
@@ -717,9 +768,10 @@ export class AgentHarness {
|
|
|
717
768
|
store: this.layerStateStore,
|
|
718
769
|
itemSchemas: this.itemSchemas,
|
|
719
770
|
forceAtomic: this.config.forceAtomicRecall,
|
|
771
|
+
peek: opts?.peek,
|
|
720
772
|
});
|
|
721
773
|
}
|
|
722
|
-
async recallLayersEventual(layers, input, ctx, budgets) {
|
|
774
|
+
async recallLayersEventual(layers, input, ctx, budgets, opts) {
|
|
723
775
|
return recallLayersEventual({
|
|
724
776
|
layers,
|
|
725
777
|
query: input,
|
|
@@ -730,6 +782,7 @@ export class AgentHarness {
|
|
|
730
782
|
itemSchemas: this.itemSchemas,
|
|
731
783
|
forceAtomic: this.config.forceAtomicRecall,
|
|
732
784
|
cache: this.recallCache,
|
|
785
|
+
peek: opts?.peek,
|
|
733
786
|
});
|
|
734
787
|
}
|
|
735
788
|
/**
|
|
@@ -868,7 +921,11 @@ export class AgentHarness {
|
|
|
868
921
|
* whose `id` is already the original `executionId`.
|
|
869
922
|
*/
|
|
870
923
|
async restore(executionId, opts) {
|
|
871
|
-
|
|
924
|
+
const ctx = await restoreFromCheckpoint(this, executionId, opts);
|
|
925
|
+
if (ctx) {
|
|
926
|
+
this.restoredExecutions.add(ctx.id);
|
|
927
|
+
}
|
|
928
|
+
return ctx;
|
|
872
929
|
}
|
|
873
930
|
/**
|
|
874
931
|
* Discard everything `restore(executionId)` would have used — the snapshot *and* the
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { CallModelRequest, DecideRequest, DecideResponse, LLMResponse } from '@noetic-tools/types';
|
|
2
|
+
import type { OpenRouter } from '@openrouter/sdk';
|
|
3
|
+
/** @internal The slice of the SDK client the decide caller uses. */
|
|
4
|
+
export type DecisionsClient = Pick<OpenRouter, 'alpha' | 'models'>;
|
|
5
|
+
/** @internal */
|
|
6
|
+
export interface DecideCallerDeps {
|
|
7
|
+
client?: DecisionsClient;
|
|
8
|
+
callModel: (request: CallModelRequest) => Promise<LLMResponse>;
|
|
9
|
+
/** Per-harness cache: model id → whether it is a decision model (`undefined` while unknown). */
|
|
10
|
+
nativeModels: Map<string, Promise<boolean | undefined>>;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Answer a decide request. Decision models (those whose OpenRouter output
|
|
14
|
+
* modality is `decisions`) answer natively with their own distributions; any
|
|
15
|
+
* other model answers through a structured-output call that estimates them.
|
|
16
|
+
*
|
|
17
|
+
* @internal
|
|
18
|
+
*/
|
|
19
|
+
export declare function callDecide(request: DecideRequest, deps: DecideCallerDeps): Promise<DecideResponse>;
|