@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.
Files changed (39) hide show
  1. package/dist/builders/control-flow-builders.d.ts +6 -4
  2. package/dist/builders/control-flow-builders.js +3 -2
  3. package/dist/builders/decide-builders.d.ts +86 -0
  4. package/dist/builders/decide-builders.js +230 -0
  5. package/dist/builders/dynamic-workflow.js +1 -0
  6. package/dist/builders/workflow-hydrator.js +81 -2
  7. package/dist/conditions/conditions.d.ts +9 -3
  8. package/dist/conditions/conditions.js +84 -25
  9. package/dist/harness/agent-harness.d.ts +18 -3
  10. package/dist/harness/agent-harness.js +63 -6
  11. package/dist/harness/decide-call.d.ts +19 -0
  12. package/dist/harness/decide-call.js +483 -0
  13. package/dist/harness/deps/adapters.d.ts +1 -0
  14. package/dist/harness/deps/adapters.js +1 -0
  15. package/dist/harness/deps/context.d.ts +1 -1
  16. package/dist/harness/deps/context.js +1 -1
  17. package/dist/harness/deps/types.d.ts +1 -1
  18. package/dist/index.d.ts +14 -6
  19. package/dist/index.js +6 -2
  20. package/dist/interpreter/action-deps.d.ts +1 -1
  21. package/dist/interpreter/action-deps.js +1 -1
  22. package/dist/interpreter/action-types.d.ts +1 -1
  23. package/dist/interpreter/collect-tools.js +2 -0
  24. package/dist/interpreter/execute-action.js +3 -20
  25. package/dist/interpreter/execute-control.js +1 -1
  26. package/dist/interpreter/execute-decide.d.ts +10 -0
  27. package/dist/interpreter/execute-decide.js +417 -0
  28. package/dist/interpreter/execute.js +8 -3
  29. package/dist/observability/genai-attributes.d.ts +6 -0
  30. package/dist/observability/genai-attributes.js +6 -0
  31. package/dist/portable/context-layers.d.ts +1 -1
  32. package/dist/portable/context-layers.js +1 -1
  33. package/dist/runtime/context-impl.d.ts +3 -0
  34. package/dist/runtime/context-impl.js +2 -0
  35. package/dist/schemas/workflow.d.ts +1 -1
  36. package/dist/util/status-code.d.ts +2 -0
  37. package/dist/util/status-code.js +7 -0
  38. package/package.json +7 -6
  39. 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>): Promise<RecallLayerOutput[]>;
299
- recallLayersEventual(layers: ContextLayer[], input: string, ctx: Context, budgets: Map<string, number>): Promise<RecallLayerOutput[]>;
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 { createInMemoryFsAdapter, createInMemoryShellAdapter, createInMemorySubprocessAdapter, OpenRouter, } from './deps/adapters.js';
6
- import { afterModelCallLayers, allocateBudgets, assembleView, beforeToolCallLayers, completeLayers, contextToExecCtx, createContextCacheStore, createLayerStateStore, createRecallCache, DEFAULT_PROJECTION, disposeLayers, executeRerender, initLayers, projectHistoryLayers, recallLayers, recallLayersAtomic, recallLayersEventual, resolveLayerTools, runAppendPipeline, storeLayers, } from './deps/context.js';
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
- await this.initLayers(layers, ctx, storage);
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
- return restoreFromCheckpoint(this, executionId, opts);
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>;