@noetic-tools/core 3.2.0 → 5.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 (96) hide show
  1. package/dist/adapters/in-memory-subprocess/manifest-persistence.d.ts +1 -1
  2. package/dist/adapters/in-memory-subprocess/types.d.ts +1 -1
  3. package/dist/adapters/openrouter.d.ts +2 -2
  4. package/dist/adapters/openrouter.js +2 -2
  5. package/dist/builders/context-builder.d.ts +11 -0
  6. package/dist/builders/context-builder.js +15 -0
  7. package/dist/builders/context-option.d.ts +23 -0
  8. package/dist/builders/context-option.js +22 -0
  9. package/dist/builders/control-flow-builders.d.ts +19 -19
  10. package/dist/builders/every.d.ts +4 -4
  11. package/dist/builders/layer-provides-builders.d.ts +1 -1
  12. package/dist/builders/layer-provides-builders.js +1 -1
  13. package/dist/builders/loop-builder.d.ts +3 -3
  14. package/dist/builders/provide-builder.d.ts +14 -7
  15. package/dist/builders/provide-builder.js +15 -4
  16. package/dist/builders/spawn-builder.d.ts +8 -6
  17. package/dist/builders/spawn-builder.js +7 -2
  18. package/dist/builders/step-builders.d.ts +19 -20
  19. package/dist/builders/tool-builder.d.ts +9 -5
  20. package/dist/builders/tool-builder.js +3 -2
  21. package/dist/builders/workflow-hydrator.d.ts +17 -4
  22. package/dist/builders/workflow-hydrator.js +87 -8
  23. package/dist/builders/workflow-step.d.ts +61 -0
  24. package/dist/builders/workflow-step.js +126 -0
  25. package/dist/conditions/conditions.d.ts +17 -17
  26. package/dist/conditions/conditions.js +1 -1
  27. package/dist/deprecated.d.ts +30 -0
  28. package/dist/deprecated.js +28 -0
  29. package/dist/harness/agent-harness.d.ts +42 -26
  30. package/dist/harness/agent-harness.js +68 -21
  31. package/dist/harness/deps/{memory.d.ts → context.d.ts} +2 -2
  32. package/dist/harness/deps/{memory.js → context.js} +1 -1
  33. package/dist/harness/deps/types.d.ts +1 -1
  34. package/dist/harness/model-schema.d.ts +2 -2
  35. package/dist/index.d.ts +21 -17
  36. package/dist/index.js +14 -8
  37. package/dist/interpreter/action-deps.d.ts +3 -3
  38. package/dist/interpreter/action-deps.js +2 -2
  39. package/dist/interpreter/action-types.d.ts +1 -1
  40. package/dist/interpreter/collect-tools.d.ts +1 -1
  41. package/dist/interpreter/execute-action.d.ts +10 -10
  42. package/dist/interpreter/execute-action.js +13 -13
  43. package/dist/interpreter/execute-control.d.ts +4 -4
  44. package/dist/interpreter/execute-control.js +1 -1
  45. package/dist/interpreter/execute-sub-harness.d.ts +1 -1
  46. package/dist/interpreter/execute.d.ts +3 -3
  47. package/dist/interpreter/execute.js +78 -31
  48. package/dist/interpreter/step-dispatcher.d.ts +3 -3
  49. package/dist/interpreter/sub-harness-events.d.ts +2 -2
  50. package/dist/interpreter/typeguards.d.ts +4 -4
  51. package/dist/patterns/dynamic-workflow.d.ts +7 -4
  52. package/dist/patterns/dynamic-workflow.js +2 -0
  53. package/dist/patterns/interview.d.ts +2 -2
  54. package/dist/patterns/plans.d.ts +5 -5
  55. package/dist/patterns/ralph-wiggum.d.ts +2 -2
  56. package/dist/patterns/react.d.ts +7 -5
  57. package/dist/patterns/react.js +6 -4
  58. package/dist/portable/builders.js +2 -0
  59. package/dist/portable/context-layers.d.ts +8 -0
  60. package/dist/portable/context-layers.js +8 -0
  61. package/dist/portable.d.ts +2 -2
  62. package/dist/portable.js +2 -2
  63. package/dist/runtime/channel-store.d.ts +33 -0
  64. package/dist/runtime/channel-store.js +297 -11
  65. package/dist/runtime/context-deps.d.ts +2 -2
  66. package/dist/runtime/context-deps.js +1 -1
  67. package/dist/runtime/context-impl.d.ts +10 -8
  68. package/dist/runtime/context-impl.js +11 -7
  69. package/dist/runtime/context-type-deps.d.ts +1 -1
  70. package/dist/runtime/durable/checkpoint-store.d.ts +1 -1
  71. package/dist/runtime/durable/harness-checkpoints.d.ts +2 -3
  72. package/dist/runtime/durable/harness-checkpoints.js +2 -3
  73. package/dist/runtime/durable/step-ledger.d.ts +1 -1
  74. package/dist/runtime/durable/step-ledger.js +1 -1
  75. package/dist/runtime/in-memory-storage.d.ts +1 -1
  76. package/dist/runtime/session-runner.d.ts +1 -1
  77. package/dist/runtime/step-registry.d.ts +3 -3
  78. package/dist/runtime/{tool-memory.d.ts → tool-context.d.ts} +1 -2
  79. package/dist/runtime/{tool-memory.js → tool-context.js} +5 -2
  80. package/dist/runtime/tool-ui.d.ts +1 -1
  81. package/dist/runtime/tool-ui.js +1 -1
  82. package/dist/schemas/workflow.d.ts +5 -279
  83. package/dist/schemas/workflow.js +4 -376
  84. package/dist/types/mutable-context.d.ts +2 -2
  85. package/dist/types/step-registrar.d.ts +1 -1
  86. package/dist/unstable.d.ts +5 -5
  87. package/dist/unstable.js +3 -3
  88. package/dist/until/predicates.d.ts +1 -1
  89. package/package.json +4 -4
  90. package/schema/noetic-workflow.schema.json +28 -0
  91. package/dist/builders/memory-builder.d.ts +0 -11
  92. package/dist/builders/memory-builder.js +0 -15
  93. package/dist/patterns/flow.d.ts +0 -2
  94. package/dist/patterns/flow.js +0 -1
  95. package/dist/portable/memory-layers.d.ts +0 -8
  96. package/dist/portable/memory-layers.js +0 -8
@@ -12,6 +12,15 @@ export interface ChannelSendOpts {
12
12
  export declare class ChannelStore {
13
13
  private channels;
14
14
  private closedExecutions;
15
+ /**
16
+ * Ids a `ChannelHandle` was issued for. Handles have no dispose lifecycle,
17
+ * so these are the only ids whose closure must be durably recorded (for
18
+ * `handle.closed` / `channel_closed`). Streams are closed directly through
19
+ * `subscribersByExecution`, so stream-only ids never accumulate here — a
20
+ * session harness closing one root id per turn stays bounded.
21
+ */
22
+ private handleObserved;
23
+ private subscribersByExecution;
15
24
  private getOrCreate;
16
25
  /**
17
26
  * Subscribe to wake notifications on a channel without consuming any value.
@@ -53,6 +62,30 @@ export declare class ChannelStore {
53
62
  * dropped (with a warning) so external callers never block.
54
63
  */
55
64
  private sendExternal;
65
+ /**
66
+ * External-reader subscription (spec 06, External Subscriptions). Delivery
67
+ * by mode: `topic` is a persistent non-lossy tap (per-subscriber bounded
68
+ * buffer, no replay of pre-subscribe values), `queue` competes with internal
69
+ * `recv` waiters FIFO (external consumption frees parked senders), `value`
70
+ * yields the current value then conflated updates.
71
+ *
72
+ * Channel state is keyed by NAME — `executionId` bounds only the
73
+ * subscription's lifetime (it ends when `closeExecution(executionId)`
74
+ * runs; queued values present at close drain first), never which values
75
+ * are delivered. An id that is never closed yields an unbounded stream
76
+ * the caller ends with `iterator.return()`. External waiters never time
77
+ * out — they end via close instead. The returned iterable owns a single
78
+ * iterator (generator semantics): subscribe again for a second consumer.
79
+ */
80
+ subscribe<T>(channel: ExternalChannel<T>, executionId: string): AsyncIterable<T>;
81
+ /** Shift the queue head and promote the oldest parked sender into the freed slot. */
82
+ private dequeueHead;
56
83
  getHandle<T>(channel: ExternalChannel<T>, executionId: string): ChannelHandle<T>;
57
84
  closeExecution(executionId: string): void;
85
+ /**
86
+ * A root run is (re)starting on this execution id: clear any previous
87
+ * closure so checkpoint-restored and sequentially re-run root contexts get
88
+ * working channels again instead of a permanently poisoned id.
89
+ */
90
+ openExecution(executionId: string): void;
58
91
  }
@@ -12,6 +12,15 @@ function cancelledError(signal) {
12
12
  export class ChannelStore {
13
13
  channels = new Map();
14
14
  closedExecutions = new Set();
15
+ /**
16
+ * Ids a `ChannelHandle` was issued for. Handles have no dispose lifecycle,
17
+ * so these are the only ids whose closure must be durably recorded (for
18
+ * `handle.closed` / `channel_closed`). Streams are closed directly through
19
+ * `subscribersByExecution`, so stream-only ids never accumulate here — a
20
+ * session harness closing one root id per turn stays bounded.
21
+ */
22
+ handleObserved = new Set();
23
+ subscribersByExecution = new Map();
15
24
  getOrCreate(channel) {
16
25
  let state = frameworkCast(this.channels.get(channel.name));
17
26
  if (!state) {
@@ -25,6 +34,7 @@ export class ChannelStore {
25
34
  pendingSenders: [],
26
35
  topicSubscribers: new Set(),
27
36
  wakeSubscribers: new Set(),
37
+ externalSubscribers: new Set(),
28
38
  };
29
39
  this.channels.set(channel.name, frameworkCast(state));
30
40
  }
@@ -79,6 +89,9 @@ export class ChannelStore {
79
89
  waiter.resolve(value);
80
90
  }
81
91
  }
92
+ for (const sub of state.externalSubscribers) {
93
+ sub.push(value);
94
+ }
82
95
  break;
83
96
  case 'queue':
84
97
  if (state.queueWaiters.length > 0) {
@@ -96,6 +109,9 @@ export class ChannelStore {
96
109
  for (const sub of state.topicSubscribers) {
97
110
  sub(value);
98
111
  }
112
+ for (const sub of state.externalSubscribers) {
113
+ sub.push(value);
114
+ }
99
115
  break;
100
116
  }
101
117
  this.fireWakes(state);
@@ -206,10 +222,9 @@ export class ChannelStore {
206
222
  }
207
223
  return this.waitWithTimeout(state.valueWaiters, channel.name, timeout, signal);
208
224
  case 'queue': {
209
- if (state.queue.length > 0) {
210
- const head = state.queue.shift();
211
- this.promotePendingSender(state);
212
- return head;
225
+ const head = this.dequeueHead(state);
226
+ if (head) {
227
+ return head.value;
213
228
  }
214
229
  // capacity-0 edge: senders can be parked while the queue is empty —
215
230
  // hand the oldest parked value straight to this receiver.
@@ -268,12 +283,10 @@ export class ChannelStore {
268
283
  case 'value':
269
284
  return state.hasValue ? state.currentValue : null;
270
285
  case 'queue': {
271
- if (state.queue.length > 0) {
272
- const head = state.queue.shift();
273
- this.promotePendingSender(state);
274
- return head;
275
- }
276
- return null;
286
+ // Explicit head check (not `?? null`): a stored `undefined` must come
287
+ // back as `undefined`, distinguishable from the empty-queue sentinel.
288
+ const head = this.dequeueHead(state);
289
+ return head ? head.value : null;
277
290
  }
278
291
  case 'topic':
279
292
  return null;
@@ -359,7 +372,96 @@ export class ChannelStore {
359
372
  // synchronously — nothing can park here.
360
373
  void this.send(channel, value);
361
374
  }
375
+ /**
376
+ * External-reader subscription (spec 06, External Subscriptions). Delivery
377
+ * by mode: `topic` is a persistent non-lossy tap (per-subscriber bounded
378
+ * buffer, no replay of pre-subscribe values), `queue` competes with internal
379
+ * `recv` waiters FIFO (external consumption frees parked senders), `value`
380
+ * yields the current value then conflated updates.
381
+ *
382
+ * Channel state is keyed by NAME — `executionId` bounds only the
383
+ * subscription's lifetime (it ends when `closeExecution(executionId)`
384
+ * runs; queued values present at close drain first), never which values
385
+ * are delivered. An id that is never closed yields an unbounded stream
386
+ * the caller ends with `iterator.return()`. External waiters never time
387
+ * out — they end via close instead. The returned iterable owns a single
388
+ * iterator (generator semantics): subscribe again for a second consumer.
389
+ */
390
+ subscribe(channel, executionId) {
391
+ if (this.closedExecutions.has(executionId)) {
392
+ return CLOSED_ITERABLE;
393
+ }
394
+ const state = this.getOrCreate(channel);
395
+ const subscriber = new ExternalSubscriber({
396
+ channelName: channel.name,
397
+ conflate: state.mode === 'value',
398
+ takeShared: state.mode === 'queue'
399
+ ? () => {
400
+ const head = this.dequeueHead(state);
401
+ if (head) {
402
+ return head;
403
+ }
404
+ // capacity-0 edge: hand a parked sender's value straight over.
405
+ const sender = state.pendingSenders.shift();
406
+ if (!sender) {
407
+ return null;
408
+ }
409
+ sender.resolve();
410
+ return {
411
+ value: sender.value,
412
+ };
413
+ }
414
+ : undefined,
415
+ parkShared: state.mode === 'queue'
416
+ ? (waiter) => {
417
+ state.queueWaiters.push(waiter);
418
+ return () => {
419
+ const idx = state.queueWaiters.indexOf(waiter);
420
+ if (idx >= 0) {
421
+ state.queueWaiters.splice(idx, 1);
422
+ }
423
+ };
424
+ }
425
+ : undefined,
426
+ onFinish: () => {
427
+ state.externalSubscribers.delete(subscriber);
428
+ const byExecution = this.subscribersByExecution.get(executionId);
429
+ if (byExecution) {
430
+ byExecution.delete(erased);
431
+ if (byExecution.size === 0) {
432
+ this.subscribersByExecution.delete(executionId);
433
+ }
434
+ }
435
+ },
436
+ });
437
+ const erased = frameworkCast(subscriber);
438
+ if (state.mode !== 'queue') {
439
+ state.externalSubscribers.add(subscriber);
440
+ }
441
+ if (state.mode === 'value' && state.hasValue) {
442
+ subscriber.push(state.currentValue);
443
+ }
444
+ let byExecution = this.subscribersByExecution.get(executionId);
445
+ if (!byExecution) {
446
+ byExecution = new Set();
447
+ this.subscribersByExecution.set(executionId, byExecution);
448
+ }
449
+ byExecution.add(erased);
450
+ return subscriber;
451
+ }
452
+ /** Shift the queue head and promote the oldest parked sender into the freed slot. */
453
+ dequeueHead(state) {
454
+ if (state.queue.length === 0) {
455
+ return null;
456
+ }
457
+ const head = state.queue.shift();
458
+ this.promotePendingSender(state);
459
+ return {
460
+ value: head,
461
+ };
462
+ }
362
463
  getHandle(channel, executionId) {
464
+ this.handleObserved.add(executionId);
363
465
  const store = this;
364
466
  return {
365
467
  get closed() {
@@ -378,6 +480,190 @@ export class ChannelStore {
378
480
  };
379
481
  }
380
482
  closeExecution(executionId) {
381
- this.closedExecutions.add(executionId);
483
+ // Closure is durably recorded only for ids with issued handles — see
484
+ // `handleObserved`. Consequence: a handle taken AFTER an execution
485
+ // completed reads `closed === false`, and a stream subscribed after a
486
+ // stream-only execution completed waits instead of ending; take handles
487
+ // and subscribe before running.
488
+ if (this.handleObserved.has(executionId)) {
489
+ this.closedExecutions.add(executionId);
490
+ }
491
+ const subscribers = this.subscribersByExecution.get(executionId);
492
+ if (!subscribers) {
493
+ return;
494
+ }
495
+ this.subscribersByExecution.delete(executionId);
496
+ for (const subscriber of subscribers) {
497
+ subscriber.close();
498
+ }
499
+ }
500
+ /**
501
+ * A root run is (re)starting on this execution id: clear any previous
502
+ * closure so checkpoint-restored and sequentially re-run root contexts get
503
+ * working channels again instead of a permanently poisoned id.
504
+ */
505
+ openExecution(executionId) {
506
+ this.closedExecutions.delete(executionId);
507
+ }
508
+ }
509
+ const MAX_EXTERNAL_BUFFER = 1_000;
510
+ const CLOSED_ITERABLE = {
511
+ [Symbol.asyncIterator]() {
512
+ return this;
513
+ },
514
+ next() {
515
+ return Promise.resolve({
516
+ value: undefined,
517
+ done: true,
518
+ });
519
+ },
520
+ };
521
+ /**
522
+ * The iterator behind `ChannelStore.subscribe`. Topic/value subscribers are
523
+ * push-fed via `push()`; queue subscribers pull from the shared queue state so
524
+ * they compete fairly with internal `recv` waiters. `close()` (execution
525
+ * completed) lets already-buffered values drain before ending; `return()`
526
+ * (consumer walked away) drops them.
527
+ */
528
+ class ExternalSubscriber {
529
+ opts;
530
+ buffer = [];
531
+ waiters = [];
532
+ parked = [];
533
+ done = false;
534
+ /** Consumer called return(): stop pulling from the shared queue. */
535
+ detached = false;
536
+ constructor(opts) {
537
+ this.opts = opts;
538
+ }
539
+ [Symbol.asyncIterator]() {
540
+ return this;
541
+ }
542
+ /** Deliver a value to this subscriber (topic/value modes). */
543
+ push(value) {
544
+ if (this.done) {
545
+ return;
546
+ }
547
+ const waiter = this.waiters.shift();
548
+ if (waiter) {
549
+ waiter({
550
+ value,
551
+ done: false,
552
+ });
553
+ return;
554
+ }
555
+ if (this.opts.conflate) {
556
+ this.buffer = [
557
+ value,
558
+ ];
559
+ return;
560
+ }
561
+ if (this.buffer.length >= MAX_EXTERNAL_BUFFER) {
562
+ console.warn(`[noetic] Channel '${this.opts.channelName}': external subscriber buffer at capacity (${MAX_EXTERNAL_BUFFER}), dropping oldest value.`);
563
+ this.buffer.shift();
564
+ }
565
+ this.buffer.push(value);
566
+ }
567
+ next() {
568
+ if (this.buffer.length > 0) {
569
+ return Promise.resolve({
570
+ value: this.buffer.shift(),
571
+ done: false,
572
+ });
573
+ }
574
+ // Live shared-queue reads stop at close — close() snapshots the queue
575
+ // into this.buffer, so a closed iterator can never steal values sent to
576
+ // a later execution on the same channel name.
577
+ const taken = this.done ? null : this.opts.takeShared?.();
578
+ if (taken) {
579
+ return Promise.resolve({
580
+ value: taken.value,
581
+ done: false,
582
+ });
583
+ }
584
+ if (this.done) {
585
+ return Promise.resolve({
586
+ value: undefined,
587
+ done: true,
588
+ });
589
+ }
590
+ if (this.opts.parkShared) {
591
+ return this.parkInSharedQueue(this.opts.parkShared);
592
+ }
593
+ return new Promise((resolve) => {
594
+ this.waiters.push(resolve);
595
+ });
596
+ }
597
+ return() {
598
+ this.detached = true;
599
+ this.buffer = [];
600
+ this.close();
601
+ return Promise.resolve({
602
+ value: undefined,
603
+ done: true,
604
+ });
605
+ }
606
+ /** End the iterator: settle every pending `next()` and unregister. Buffered values still drain. */
607
+ close() {
608
+ if (this.done) {
609
+ return;
610
+ }
611
+ // Snapshot the shared queue's current contents into the private buffer
612
+ // ("buffered values drain first") — after this the iterator never touches
613
+ // live channel state again. A detached iterator (return()) walked away
614
+ // and drains nothing.
615
+ if (!this.detached && this.opts.takeShared) {
616
+ for (let taken = this.opts.takeShared(); taken; taken = this.opts.takeShared()) {
617
+ this.buffer.push(taken.value);
618
+ }
619
+ }
620
+ this.done = true;
621
+ this.opts.onFinish();
622
+ for (const entry of this.parked.splice(0)) {
623
+ entry.unpark();
624
+ entry.settleDone();
625
+ }
626
+ for (const waiter of this.waiters.splice(0)) {
627
+ waiter({
628
+ value: undefined,
629
+ done: true,
630
+ });
631
+ }
632
+ }
633
+ /**
634
+ * Queue mode: wait in the channel's shared waiter FIFO. No timer attaches,
635
+ * so external waiters never reject with `channel_timeout` — `close()` ends
636
+ * them instead.
637
+ */
638
+ parkInSharedQueue(parkShared) {
639
+ return new Promise((resolve) => {
640
+ const entry = {
641
+ unpark: () => { },
642
+ settleDone: () => resolve({
643
+ value: undefined,
644
+ done: true,
645
+ }),
646
+ };
647
+ const removeParked = () => {
648
+ const idx = this.parked.indexOf(entry);
649
+ if (idx >= 0) {
650
+ this.parked.splice(idx, 1);
651
+ }
652
+ };
653
+ entry.unpark = parkShared({
654
+ resolve: (value) => {
655
+ removeParked();
656
+ resolve({
657
+ value,
658
+ done: false,
659
+ });
660
+ },
661
+ reject: () => {
662
+ removeParked();
663
+ entry.settleDone();
664
+ },
665
+ });
666
+ this.parked.push(entry);
667
+ });
382
668
  }
383
669
  }
@@ -1,4 +1,4 @@
1
- export { buildContextMemory } from '@noetic-tools/memory';
1
+ export { buildContextData } from '@noetic-tools/context';
2
2
  export type { ItemSchemaRegistry } from '@noetic-tools/types';
3
3
  export { defaultItemSchemaRegistry } from '@noetic-tools/types';
4
- export type { AgentHarnessContract, Channel, ChannelStore, Context, ContextMemory, CwdState, EventBroadcaster, FrontierFrame, FsAdapter, Item, ItemLog, LastLayerUsage, MemoryLayer, Span, StepMeta, TokenUsage, Tool, } from './context-type-deps.js';
4
+ export type { AgentHarnessContract, Channel, ChannelStore, Context, ContextData, ContextLayer, CwdState, EventBroadcaster, FrontierFrame, FsAdapter, Item, ItemLog, LastLayerUsage, Span, StepMeta, TokenUsage, Tool, } from './context-type-deps.js';
@@ -1,2 +1,2 @@
1
- export { buildContextMemory } from '@noetic-tools/memory';
1
+ export { buildContextData } from '@noetic-tools/context';
2
2
  export { defaultItemSchemaRegistry } from '@noetic-tools/types';
@@ -1,4 +1,4 @@
1
- import type { AgentHarnessContract, Channel, ChannelStore, Context, ContextMemory, CwdState, EventBroadcaster, FrontierFrame, FsAdapter, Item, ItemLog, ItemSchemaRegistry, LastLayerUsage, MemoryLayer, Span, StepMeta, TokenUsage, Tool } from './context-deps.js';
1
+ import type { AgentHarnessContract, Channel, ChannelStore, Context, ContextData, ContextLayer, CwdState, EventBroadcaster, FrontierFrame, FsAdapter, Item, ItemLog, ItemSchemaRegistry, LastLayerUsage, Span, StepMeta, TokenUsage, Tool } from './context-deps.js';
2
2
  import type { StepLedger } from './durable/step-ledger.js';
3
3
  /**
4
4
  * @internal
@@ -7,13 +7,13 @@ import type { StepLedger } from './durable/step-ledger.js';
7
7
  * children, so a foreign `Context` implementation yields just itself.
8
8
  */
9
9
  export declare function collectContextTree(ctx: Context): Context[];
10
- export declare class ContextImpl implements Context<ContextMemory> {
10
+ export declare class ContextImpl implements Context<ContextData> {
11
11
  readonly id: string;
12
12
  stepCount: number;
13
13
  tokens: TokenUsage;
14
14
  cost: number;
15
15
  state: unknown;
16
- readonly parent: Context<ContextMemory> | null;
16
+ readonly parent: Context<ContextData> | null;
17
17
  readonly depth: number;
18
18
  readonly span: Span;
19
19
  readonly threadId: string;
@@ -22,7 +22,7 @@ export declare class ContextImpl implements Context<ContextMemory> {
22
22
  lastStepMeta: StepMeta | null;
23
23
  lastLayerUsage: LastLayerUsage | undefined;
24
24
  readonly harness: AgentHarnessContract;
25
- readonly layers?: MemoryLayer[];
25
+ readonly layers?: ContextLayer[];
26
26
  unifiedTools?: ReadonlyArray<Tool>;
27
27
  readonly itemSchemas?: ItemSchemaRegistry;
28
28
  readonly cwdState: CwdState;
@@ -60,7 +60,7 @@ export declare class ContextImpl implements Context<ContextMemory> {
60
60
  * @internal
61
61
  */
62
62
  private readonly _children;
63
- private _memory?;
63
+ private _contextData?;
64
64
  /**
65
65
  * Stack of steps currently in flight on this context, most-recent last.
66
66
  * Pushed by `enterStep` at the top of `execute()` and popped by
@@ -109,7 +109,7 @@ export declare class ContextImpl implements Context<ContextMemory> {
109
109
  pathPrefix?: string;
110
110
  /** The execution's completion ledger, shared with children by reference. */
111
111
  ledger?: StepLedger;
112
- layers?: MemoryLayer[];
112
+ layers?: ContextLayer[];
113
113
  unifiedTools?: ReadonlyArray<Tool>;
114
114
  itemSchemas?: ItemSchemaRegistry;
115
115
  cwdState?: CwdState;
@@ -118,7 +118,7 @@ export declare class ContextImpl implements Context<ContextMemory> {
118
118
  * Pre-chosen context id. When set, the ContextImpl adopts this id instead
119
119
  * of generating a fresh UUID. Used by `executeSpawn` so the child's
120
120
  * `ctx.id` matches the `executionId` keyed into the layer-state store —
121
- * otherwise writes via `ctx.memory[layerId].state` land on one id while
121
+ * otherwise writes via `ctx.context[layerId].state` land on one id while
122
122
  * spawn's `onReturn` reads from another, silently losing the update.
123
123
  */
124
124
  id?: string;
@@ -149,7 +149,9 @@ export declare class ContextImpl implements Context<ContextMemory> {
149
149
  get fs(): FsAdapter;
150
150
  get shell(): AgentHarnessContract['shell'];
151
151
  get subprocess(): AgentHarnessContract['subprocess'];
152
- get memory(): ContextMemory;
152
+ get context(): ContextData;
153
+ /** @deprecated Renamed to `context`. Returns the same object. */
154
+ get memory(): ContextData;
153
155
  recv<T>(ch: Channel<T>, opts?: {
154
156
  timeout?: number;
155
157
  }): Promise<T>;
@@ -1,6 +1,6 @@
1
- import { buildContextMemory, defaultItemSchemaRegistry } from './context-deps.js';
1
+ import { buildContextData, defaultItemSchemaRegistry } from './context-deps.js';
2
2
  import { ItemLogImpl } from './item-log-impl.js';
3
- const EMPTY_MEMORY = Object.freeze({});
3
+ const EMPTY_CONTEXT = Object.freeze({});
4
4
  class NoopSpan {
5
5
  traceId = crypto.randomUUID();
6
6
  spanId = crypto.randomUUID();
@@ -84,7 +84,7 @@ export class ContextImpl {
84
84
  * @internal
85
85
  */
86
86
  _children = new Set();
87
- _memory;
87
+ _contextData;
88
88
  /**
89
89
  * Stack of steps currently in flight on this context, most-recent last.
90
90
  * Pushed by `enterStep` at the top of `execute()` and popped by
@@ -203,11 +203,15 @@ export class ContextImpl {
203
203
  get subprocess() {
204
204
  return this.harness.subprocess;
205
205
  }
206
- get memory() {
207
- if (!this._memory) {
208
- this._memory = this.layers ? buildContextMemory(this.layers, this) : EMPTY_MEMORY;
206
+ get context() {
207
+ if (!this._contextData) {
208
+ this._contextData = this.layers ? buildContextData(this.layers, this) : EMPTY_CONTEXT;
209
209
  }
210
- return this._memory;
210
+ return this._contextData;
211
+ }
212
+ /** @deprecated Renamed to `context`. Returns the same object. */
213
+ get memory() {
214
+ return this.context;
211
215
  }
212
216
  recv(ch, opts) {
213
217
  if (!this.channelStore) {
@@ -1,4 +1,4 @@
1
- export type { ContextMemory, MemoryLayer } from '@noetic-tools/memory';
1
+ export type { ContextData, ContextLayer } from '@noetic-tools/context';
2
2
  export type { AgentHarnessContract, Channel, Context, CwdState, FsAdapter, Item, ItemLog, LastLayerUsage, Span, StepMeta, TokenUsage, Tool, } from '@noetic-tools/types';
3
3
  export type { FrontierFrame } from '../types/checkpoint.js';
4
4
  export type { ChannelStore } from './channel-store.js';
@@ -1,4 +1,4 @@
1
- import type { StorageAdapter } from '@noetic-tools/memory';
1
+ import type { StorageAdapter } from '@noetic-tools/context';
2
2
  import type { CheckpointSnapshot } from '../../types/checkpoint.js';
3
3
  export declare const CheckpointKeys: {
4
4
  readonly ExecPrefix: "execution:";
@@ -1,4 +1,4 @@
1
- import type { LayerStateStore, MemoryLayer } from '@noetic-tools/memory';
1
+ import type { LayerStateStore } from '@noetic-tools/context';
2
2
  import type { Context, Item, ItemSchemaRegistry, RestoreContextOptions } from '@noetic-tools/types';
3
3
  import type { EventBroadcaster } from '../event-broadcaster.js';
4
4
  import type { CheckpointStore } from './checkpoint-store.js';
@@ -29,7 +29,6 @@ export interface CheckpointHarnessHandle {
29
29
  readonly stepLedgerRetention?: StepLedgerRetention;
30
30
  readonly layerStateStore: LayerStateStore;
31
31
  readonly itemSchemas: ItemSchemaRegistry;
32
- readonly _memory?: MemoryLayer[];
33
32
  createContext(opts?: RestoreCheckpointOptions & {
34
33
  items?: Item[];
35
34
  threadId?: string;
@@ -52,7 +51,7 @@ export declare function captureCheckpoint(h: CheckpointHarnessHandle, ctx: Conte
52
51
  * `null` if no snapshot is recorded for `executionId`. Layer state is
53
52
  * replayed into `layerStateStore` keyed by the original executionId so
54
53
  * the restored context observes the pre-crash state through
55
- * `readLayerState` and the memory projectors.
54
+ * `readLayerState` and the context projectors.
56
55
  *
57
56
  * `opts` carries the host's own context wiring (broadcaster, parent, state,
58
57
  * layer overrides) into the rebuilt context. A snapshot cannot round-trip live
@@ -63,7 +63,7 @@ export async function captureCheckpoint(h, ctx) {
63
63
  * `null` if no snapshot is recorded for `executionId`. Layer state is
64
64
  * replayed into `layerStateStore` keyed by the original executionId so
65
65
  * the restored context observes the pre-crash state through
66
- * `readLayerState` and the memory projectors.
66
+ * `readLayerState` and the context projectors.
67
67
  *
68
68
  * `opts` carries the host's own context wiring (broadcaster, parent, state,
69
69
  * layer overrides) into the rebuilt context. A snapshot cannot round-trip live
@@ -93,7 +93,7 @@ export async function restoreFromCheckpoint(h, executionId, opts) {
93
93
  }
94
94
  const items = h.itemSchemas.parseMany(snapshot.itemLog.items);
95
95
  const cwdInit = snapshot.cwd?.current ?? undefined;
96
- /* Caller wiring first, snapshot second: a host may legitimately swap the memory
96
+ /* Caller wiring first, snapshot second: a host may legitimately swap the context
97
97
  * layers or hang the restored execution under a new parent, but it must never be
98
98
  * able to override the identity/history the snapshot is the record of. */
99
99
  const ctx = h.createContext({
@@ -102,7 +102,6 @@ export async function restoreFromCheckpoint(h, executionId, opts) {
102
102
  threadId: snapshot.threadId,
103
103
  resourceId: snapshot.resourceId,
104
104
  cwdInit,
105
- memory: opts?.memory ?? h._memory,
106
105
  });
107
106
  if (ctx instanceof ContextImpl) {
108
107
  Object.defineProperty(ctx, 'id', {
@@ -17,7 +17,7 @@
17
17
  * construction — a missing entry re-runs its step, which costs work rather than
18
18
  * correctness.
19
19
  */
20
- import type { StorageAdapter } from '@noetic-tools/memory';
20
+ import type { StorageAdapter } from '@noetic-tools/context';
21
21
  import { z } from 'zod';
22
22
  /** @public One completed step, keyed by its execution path. */
23
23
  export declare const StepLedgerEntrySchema: z.ZodObject<{
@@ -17,7 +17,7 @@
17
17
  * construction — a missing entry re-runs its step, which costs work rather than
18
18
  * correctness.
19
19
  */
20
- import { storageGetMany } from '@noetic-tools/memory';
20
+ import { storageGetMany } from '@noetic-tools/context';
21
21
  import { NoeticConfigError } from '@noetic-tools/types';
22
22
  import { z } from 'zod';
23
23
  //#region Entry
@@ -1,4 +1,4 @@
1
- import type { StorageAdapter } from '@noetic-tools/memory';
1
+ import type { StorageAdapter } from '@noetic-tools/context';
2
2
  /**
3
3
  * @public Process-local, Map-backed StorageAdapter.
4
4
  *
@@ -16,7 +16,7 @@ export interface TurnContext {
16
16
  * (so the runner is the single point of ExecuteInput → Item[] conversion),
17
17
  * plus the messages being delivered this turn so the harness can honour
18
18
  * per-turn `ExecuteOptions` (the first message's options establish
19
- * resourceId/state/memory for the turn). */
19
+ * resourceId/state/context for the turn). */
20
20
  export type CreateContextFn = (items: ReadonlyArray<Item>, turnId: string, messages: ReadonlyArray<QueuedMessage>) => Context;
21
21
  export interface SessionRunnerOpts {
22
22
  readonly threadId: string;
@@ -1,10 +1,10 @@
1
- import type { ContextMemory } from '@noetic-tools/memory';
1
+ import type { ContextData } from '@noetic-tools/context';
2
2
  import type { Step } from '@noetic-tools/types';
3
3
  /** Registry-wide step type — stored at the widest generic parameters so
4
4
  * callers can register steps with narrower input/output types without
5
5
  * fighting variance. The public `Step` default already uses `unknown` for
6
6
  * the input and output parameters, matching this shape. */
7
- type RegisteredStep = Step<ContextMemory, unknown, unknown>;
7
+ type RegisteredStep = Step<ContextData, unknown, unknown>;
8
8
  /**
9
9
  * @public
10
10
  * Registers a step so the subprocess adapter can look it up by id.
@@ -18,7 +18,7 @@ type RegisteredStep = Step<ContextMemory, unknown, unknown>;
18
18
  * `clearRegistry` wiring is deferred — see the tracked follow-up task on
19
19
  * the team's board (strict-registry-plus-test-clear).
20
20
  */
21
- export declare function registerStep<TMemory, I, O>(step: Step<TMemory, I, O>): void;
21
+ export declare function registerStep<TContext, I, O>(step: Step<TContext, I, O>): void;
22
22
  /**
23
23
  * @public
24
24
  * Looks up a registered step by id. Returns `null` when the id is not known
@@ -1,4 +1,3 @@
1
- import type { AgentHarnessContract, Context, ToolExecutionContext, ToolMemory } from '@noetic-tools/types';
1
+ import type { AgentHarnessContract, Context, ToolExecutionContext } from '@noetic-tools/types';
2
2
  import type { TurnContext } from '@openrouter/agent';
3
- export declare function buildToolMemory(harness: AgentHarnessContract, ctx: Context): ToolMemory;
4
3
  export declare function buildToolExecutionContext(ctx: Context, harness: AgentHarnessContract, turnContext?: TurnContext): ToolExecutionContext;