@noetic-tools/core 0.0.1 → 0.1.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.js +1 -1
- package/dist/adapters/in-memory-subprocess/manifest-persistence.d.ts +8 -0
- package/dist/adapters/in-memory-subprocess/manifest-persistence.js +56 -0
- package/dist/adapters/in-memory-subprocess/metadata.d.ts +12 -0
- package/dist/adapters/in-memory-subprocess/metadata.js +58 -0
- package/dist/adapters/in-memory-subprocess/step-completion.d.ts +3 -0
- package/dist/adapters/in-memory-subprocess/step-completion.js +86 -0
- package/dist/adapters/in-memory-subprocess/types.d.ts +88 -0
- package/dist/adapters/in-memory-subprocess/types.js +2 -0
- package/dist/adapters/in-memory-subprocess-adapter.d.ts +12 -4
- package/dist/adapters/in-memory-subprocess-adapter.js +164 -55
- package/dist/adapters/openrouter.d.ts +11 -2
- package/dist/adapters/openrouter.js +66 -5
- package/dist/builders/control-flow-builders.js +8 -3
- package/dist/builders/every.js +4 -1
- package/dist/builders/layer-provides-builders.d.ts +1 -32
- package/dist/builders/layer-provides-builders.js +1 -33
- package/dist/builders/loop-builder.js +4 -1
- package/dist/builders/memory-builder.js +1 -1
- package/dist/builders/provide-builder.js +4 -1
- package/dist/builders/spawn-builder.d.ts +20 -7
- package/dist/builders/spawn-builder.js +16 -2
- package/dist/builders/step-builders.d.ts +49 -28
- package/dist/builders/step-builders.js +30 -11
- package/dist/builders/tool-builder.d.ts +5 -1
- package/dist/builders/tool-builder.js +2 -0
- package/dist/builders/workflow-hydrator.d.ts +38 -0
- package/dist/builders/workflow-hydrator.js +336 -0
- package/dist/conditions/conditions.js +1 -1
- package/dist/errors/noetic-error.js +2 -0
- package/dist/{runtime → harness}/agent-harness.d.ts +65 -45
- package/dist/harness/agent-harness.js +576 -0
- package/dist/harness/deps/adapters.d.ts +4 -0
- package/dist/harness/deps/adapters.js +4 -0
- package/dist/harness/deps/interpreter.d.ts +5 -0
- package/dist/harness/deps/interpreter.js +4 -0
- package/dist/harness/deps/memory.d.ts +5 -0
- package/dist/harness/deps/memory.js +4 -0
- package/dist/harness/deps/runtime.d.ts +10 -0
- package/dist/harness/deps/runtime.js +7 -0
- package/dist/harness/deps/types.d.ts +17 -0
- package/dist/harness/deps/types.js +1 -0
- package/dist/harness/model-call.d.ts +50 -0
- package/dist/harness/model-call.js +694 -0
- package/dist/harness/model-schema.d.ts +19 -0
- package/dist/harness/model-schema.js +46 -0
- package/dist/harness/step-bootstrap.d.ts +25 -0
- package/dist/harness/step-bootstrap.js +170 -0
- package/dist/index.d.ts +48 -12
- package/dist/index.js +29 -7
- package/dist/interpreter/action-deps.d.ts +12 -0
- package/dist/interpreter/action-deps.js +10 -0
- package/dist/interpreter/action-types.d.ts +8 -0
- package/dist/interpreter/action-types.js +1 -0
- package/dist/interpreter/collect-tools.d.ts +1 -1
- package/dist/interpreter/collect-tools.js +6 -2
- package/dist/interpreter/execute-action.d.ts +22 -0
- package/dist/interpreter/execute-action.js +527 -0
- package/dist/interpreter/{execute-every.d.ts → execute-control.d.ts} +7 -1
- package/dist/interpreter/execute-control.js +530 -0
- package/dist/interpreter/execute.d.ts +13 -0
- package/dist/interpreter/execute.js +151 -48
- package/dist/interpreter/message-helpers.d.ts +1 -9
- package/dist/interpreter/message-helpers.js +1 -42
- package/dist/interpreter/step-dispatcher.d.ts +61 -0
- package/dist/interpreter/step-dispatcher.js +67 -0
- package/dist/interpreter/typeguards.d.ts +3 -10
- package/dist/interpreter/typeguards.js +3 -20
- package/dist/{runtime → memory}/exec-context-factory.js +1 -1
- package/dist/memory/flow-schema.d.ts +52 -0
- package/dist/memory/flow-schema.js +102 -0
- package/dist/memory/function-call-utils.js +4 -2
- package/dist/memory/layer-api.d.ts +1 -1
- package/dist/memory/layer-api.js +2 -2
- package/dist/memory/layer-lifecycle.d.ts +1 -1
- package/dist/memory/layer-lifecycle.js +2 -2
- package/dist/memory/layer-provides.d.ts +32 -0
- package/dist/memory/layer-provides.js +33 -0
- package/dist/memory/layer-usage.d.ts +3 -2
- package/dist/memory/layer-usage.js +9 -3
- package/dist/memory/layers/durable-task-state.js +1 -1
- package/dist/memory/layers/file-reference.js +302 -246
- package/dist/memory/layers/history-window.js +1 -1
- package/dist/memory/layers/observational-memory.js +1 -2
- package/dist/memory/layers/plan.d.ts +1 -1
- package/dist/memory/layers/plan.js +13 -8
- package/dist/memory/layers/steering.js +1 -1
- package/dist/memory/layers/tool-memory-layer.d.ts +1 -1
- package/dist/memory/layers/working-memory.js +2 -2
- package/dist/patterns/dynamic-workflow.d.ts +55 -0
- package/dist/patterns/dynamic-workflow.js +194 -0
- package/dist/patterns/flow.d.ts +2 -52
- package/dist/patterns/flow.js +1 -103
- package/dist/patterns/interview.js +1 -1
- package/dist/patterns/plans.d.ts +3 -3
- package/dist/patterns/plans.js +3 -3
- package/dist/patterns/ralph-wiggum.d.ts +1 -1
- package/dist/patterns/react.d.ts +1 -1
- package/dist/portable/adapters.d.ts +6 -0
- package/dist/portable/adapters.js +6 -0
- package/dist/portable/ask-user.d.ts +4 -0
- package/dist/portable/ask-user.js +2 -0
- package/dist/portable/builders.d.ts +12 -0
- package/dist/portable/builders.js +12 -0
- package/dist/portable/memory-layers.d.ts +12 -0
- package/dist/portable/memory-layers.js +12 -0
- package/dist/portable/runtime.d.ts +4 -0
- package/dist/portable/runtime.js +4 -0
- package/dist/portable/until.d.ts +4 -0
- package/dist/portable/until.js +4 -0
- package/dist/portable.d.ts +8 -26
- package/dist/portable.js +8 -34
- package/dist/runtime/broadcaster-utils.d.ts +5 -1
- package/dist/runtime/broadcaster-utils.js +11 -6
- package/dist/runtime/channel-store.js +1 -1
- package/dist/runtime/context-deps.d.ts +4 -0
- package/dist/runtime/context-deps.js +2 -0
- package/dist/runtime/context-impl.d.ts +42 -12
- package/dist/runtime/context-impl.js +51 -4
- package/dist/runtime/context-type-deps.d.ts +14 -0
- package/dist/runtime/context-type-deps.js +1 -0
- package/dist/runtime/detached-handle.d.ts +50 -2
- package/dist/runtime/detached-handle.js +216 -12
- package/dist/runtime/durable/checkpoint-store.d.ts +38 -0
- package/dist/runtime/durable/checkpoint-store.js +101 -0
- package/dist/runtime/durable/detached-signal.d.ts +37 -0
- package/dist/runtime/durable/detached-signal.js +52 -0
- package/dist/runtime/durable/harness-checkpoints.d.ts +51 -0
- package/dist/runtime/durable/harness-checkpoints.js +104 -0
- package/dist/runtime/durable/index.d.ts +10 -0
- package/dist/runtime/durable/index.js +5 -0
- package/dist/runtime/durable/runnable-loop.d.ts +100 -0
- package/dist/runtime/durable/runnable-loop.js +90 -0
- package/dist/runtime/durable/session-seed.d.ts +28 -0
- package/dist/runtime/durable/session-seed.js +27 -0
- package/dist/runtime/durable/stall-nudge.d.ts +82 -0
- package/dist/runtime/durable/stall-nudge.js +87 -0
- package/dist/runtime/in-memory-storage.js +1 -1
- package/dist/runtime/item-log-impl.d.ts +1 -1
- package/dist/runtime/step-registry.d.ts +42 -0
- package/dist/runtime/step-registry.js +77 -0
- package/dist/schemas/workflow.d.ts +139 -0
- package/dist/schemas/workflow.js +232 -0
- package/dist/types/ask-user-types.d.ts +57 -0
- package/dist/types/ask-user-types.js +74 -0
- package/dist/types/checkpoint.d.ts +98 -0
- package/dist/types/checkpoint.js +81 -0
- package/dist/types/common.d.ts +1 -50
- package/dist/types/context-parts/item-log.d.ts +6 -0
- package/dist/types/context-parts/item-log.js +1 -0
- package/dist/types/context-parts/layer-usage.d.ts +18 -0
- package/dist/types/context-parts/layer-usage.js +1 -0
- package/dist/types/context.d.ts +135 -26
- package/dist/types/error.d.ts +15 -0
- package/dist/types/harness-result.d.ts +1 -1
- package/dist/types/items.d.ts +18 -2
- package/dist/types/memory-context.d.ts +39 -0
- package/dist/types/memory-context.js +1 -0
- package/dist/types/memory.d.ts +35 -65
- package/dist/types/runtime.d.ts +2 -1
- package/dist/types/steering.d.ts +1 -1
- package/dist/types/step-registrar.d.ts +46 -0
- package/dist/types/step-registrar.js +56 -0
- package/dist/types/step.d.ts +30 -5
- package/dist/types/subprocess-adapter.d.ts +119 -3
- package/dist/types/subprocess-adapter.js +2 -0
- package/dist/types/tool.d.ts +64 -0
- package/dist/types/tool.js +1 -0
- package/dist/unstable.d.ts +2 -2
- package/dist/unstable.js +2 -2
- package/dist/until/predicates.d.ts +9 -0
- package/dist/until/predicates.js +14 -0
- package/dist/util/message-helpers.d.ts +17 -0
- package/dist/util/message-helpers.js +64 -0
- package/package.json +1 -1
- package/dist/adapters/local-fs-adapter.d.ts +0 -3
- package/dist/adapters/local-fs-adapter.js +0 -43
- package/dist/adapters/local-shell-adapter.d.ts +0 -51
- package/dist/adapters/local-shell-adapter.js +0 -167
- package/dist/adapters/local-subprocess-adapter.d.ts +0 -16
- package/dist/adapters/local-subprocess-adapter.js +0 -187
- package/dist/interpreter/execute-branch.d.ts +0 -3
- package/dist/interpreter/execute-branch.js +0 -10
- package/dist/interpreter/execute-every.js +0 -143
- package/dist/interpreter/execute-fork.d.ts +0 -3
- package/dist/interpreter/execute-fork.js +0 -215
- package/dist/interpreter/execute-llm.d.ts +0 -4
- package/dist/interpreter/execute-llm.js +0 -217
- package/dist/interpreter/execute-loop.d.ts +0 -3
- package/dist/interpreter/execute-loop.js +0 -171
- package/dist/interpreter/execute-provide.d.ts +0 -10
- package/dist/interpreter/execute-provide.js +0 -64
- package/dist/interpreter/execute-run.d.ts +0 -3
- package/dist/interpreter/execute-run.js +0 -39
- package/dist/interpreter/execute-spawn.d.ts +0 -11
- package/dist/interpreter/execute-spawn.js +0 -113
- package/dist/interpreter/execute-tool.d.ts +0 -5
- package/dist/interpreter/execute-tool.js +0 -81
- package/dist/runtime/agent-harness.js +0 -1170
- /package/dist/{runtime → memory}/exec-context-factory.d.ts +0 -0
- /package/dist/{interpreter → util}/framework-cast.d.ts +0 -0
- /package/dist/{interpreter → util}/framework-cast.js +0 -0
package/dist/portable.js
CHANGED
|
@@ -1,34 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
export
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
//#region Builders
|
|
10
|
-
/** @public */
|
|
11
|
-
export { step } from './builders/step-builders';
|
|
12
|
-
/** @public */
|
|
13
|
-
export { tool, toolWithGenerator } from './builders/tool-builder';
|
|
14
|
-
//#endregion
|
|
15
|
-
//#region Memory Layers
|
|
16
|
-
/** @public */
|
|
17
|
-
export { durableTaskState } from './memory/layers/durable-task-state';
|
|
18
|
-
/** @public */
|
|
19
|
-
export { historyWindow } from './memory/layers/history-window';
|
|
20
|
-
/** @public */
|
|
21
|
-
export { observationalMemory } from './memory/layers/observational-memory';
|
|
22
|
-
/** @public */
|
|
23
|
-
export { planMemory } from './memory/layers/plan';
|
|
24
|
-
/** @public */
|
|
25
|
-
export { toolMemoryLayer } from './memory/layers/tool-memory-layer';
|
|
26
|
-
/** @public */
|
|
27
|
-
export { workingMemory } from './memory/layers/working-memory';
|
|
28
|
-
//#endregion
|
|
29
|
-
//#region Runtime
|
|
30
|
-
/** @public */
|
|
31
|
-
export { AgentHarness } from './runtime/agent-harness';
|
|
32
|
-
/** @public */
|
|
33
|
-
export { createInMemoryStorage } from './runtime/in-memory-storage';
|
|
34
|
-
//#endregion
|
|
1
|
+
export * from './portable/adapters';
|
|
2
|
+
export * from './portable/ask-user';
|
|
3
|
+
export * from './portable/builders';
|
|
4
|
+
export * from './portable/memory-layers';
|
|
5
|
+
export * from './portable/runtime';
|
|
6
|
+
export * from './portable/until';
|
|
7
|
+
/** @public */
|
|
8
|
+
export { Slot } from './types/memory';
|
|
@@ -13,7 +13,11 @@ export type EmitOption = boolean | ((eventType: string, data: Record<string, unk
|
|
|
13
13
|
*/
|
|
14
14
|
export declare function shouldEmit(emit: EmitOption | undefined, eventType: string, data: Record<string, unknown>): boolean;
|
|
15
15
|
/**
|
|
16
|
-
* Get the EventBroadcaster from a context if available.
|
|
16
|
+
* Get the EventBroadcaster from a context if available. Walks up the parent
|
|
17
|
+
* chain so spawned child contexts inherit the session-level broadcaster — the
|
|
18
|
+
* interpreter never re-installs `_broadcaster` on spawn children, so without
|
|
19
|
+
* this traversal every LLM call inside a `spawn()` step would be invisible to
|
|
20
|
+
* the UI stream.
|
|
17
21
|
* Uses property check rather than instanceof to support mock contexts in tests.
|
|
18
22
|
* @internal
|
|
19
23
|
*/
|
|
@@ -26,16 +26,21 @@ function hasBroadcaster(ctx) {
|
|
|
26
26
|
return typeof ctx._broadcaster === 'object' && ctx._broadcaster !== null;
|
|
27
27
|
}
|
|
28
28
|
/**
|
|
29
|
-
* Get the EventBroadcaster from a context if available.
|
|
29
|
+
* Get the EventBroadcaster from a context if available. Walks up the parent
|
|
30
|
+
* chain so spawned child contexts inherit the session-level broadcaster — the
|
|
31
|
+
* interpreter never re-installs `_broadcaster` on spawn children, so without
|
|
32
|
+
* this traversal every LLM call inside a `spawn()` step would be invisible to
|
|
33
|
+
* the UI stream.
|
|
30
34
|
* Uses property check rather than instanceof to support mock contexts in tests.
|
|
31
35
|
* @internal
|
|
32
36
|
*/
|
|
33
37
|
export function getBroadcaster(ctx) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
let current = ctx;
|
|
39
|
+
while (current) {
|
|
40
|
+
if (hasBroadcaster(current)) {
|
|
41
|
+
return current._broadcaster;
|
|
42
|
+
}
|
|
43
|
+
current = current.parent ?? null;
|
|
39
44
|
}
|
|
40
45
|
return undefined;
|
|
41
46
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { NoeticErrorImpl } from '../errors/noetic-error';
|
|
2
|
-
import { frameworkCast } from '../
|
|
2
|
+
import { frameworkCast } from '../util/framework-cast';
|
|
3
3
|
function isExternalChannel(ch) {
|
|
4
4
|
return 'external' in ch && ch.external === true;
|
|
5
5
|
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { buildContextMemory } from '../memory/layer-api';
|
|
2
|
+
export type { ItemSchemaRegistry } from '../schemas/item';
|
|
3
|
+
export { defaultItemSchemaRegistry } from '../schemas/item';
|
|
4
|
+
export type { AgentHarnessContract, Channel, ChannelStore, Context, ContextMemory, CwdState, EventBroadcaster, FrontierFrame, FsAdapter, Item, ItemLog, LastLayerUsage, MemoryLayer, Span, StepMeta, TokenUsage, Tool, } from './context-type-deps';
|
|
@@ -1,14 +1,4 @@
|
|
|
1
|
-
import type { ItemSchemaRegistry } from '
|
|
2
|
-
import type { Channel } from '../types/channel';
|
|
3
|
-
import type { StepMeta, TokenUsage, Tool } from '../types/common';
|
|
4
|
-
import type { Context, CwdState, ItemLog, LastLayerUsage } from '../types/context';
|
|
5
|
-
import type { FsAdapter } from '../types/fs-adapter';
|
|
6
|
-
import type { Item } from '../types/items';
|
|
7
|
-
import type { ContextMemory, MemoryLayer } from '../types/memory';
|
|
8
|
-
import type { Span } from '../types/observability';
|
|
9
|
-
import type { AgentHarnessContract } from '../types/runtime';
|
|
10
|
-
import type { ChannelStore } from './channel-store';
|
|
11
|
-
import type { EventBroadcaster } from './event-broadcaster';
|
|
1
|
+
import type { AgentHarnessContract, Channel, ChannelStore, Context, ContextMemory, CwdState, EventBroadcaster, FrontierFrame, FsAdapter, Item, ItemLog, ItemSchemaRegistry, LastLayerUsage, MemoryLayer, Span, StepMeta, TokenUsage, Tool } from './context-deps';
|
|
12
2
|
export declare class ContextImpl implements Context<ContextMemory> {
|
|
13
3
|
readonly id: string;
|
|
14
4
|
stepCount: number;
|
|
@@ -34,7 +24,8 @@ export declare class ContextImpl implements Context<ContextMemory> {
|
|
|
34
24
|
/**
|
|
35
25
|
* Shared channel store for cross-context communication. Inherited by
|
|
36
26
|
* `fork` / `spawn` children so channels published by a sibling are visible
|
|
37
|
-
* to peers — see `
|
|
27
|
+
* to peers — see `executeFork` and `executeSpawn` in `interpreter/execute-action.ts`
|
|
28
|
+
* and `interpreter/execute-control.ts`.
|
|
38
29
|
* @internal
|
|
39
30
|
*/
|
|
40
31
|
readonly channelStore?: ChannelStore;
|
|
@@ -44,6 +35,15 @@ export declare class ContextImpl implements Context<ContextMemory> {
|
|
|
44
35
|
private _aborted;
|
|
45
36
|
private _abortReason?;
|
|
46
37
|
private _memory?;
|
|
38
|
+
/**
|
|
39
|
+
* Stack of steps currently in flight on this context, most-recent last.
|
|
40
|
+
* Pushed by `enterStep` at the top of `execute()` and popped by
|
|
41
|
+
* `leaveStep` when the step resolves (success or failure). The harness'
|
|
42
|
+
* checkpoint writer serialises this stack as the execution frontier so
|
|
43
|
+
* a restart can identify which step the context was paused inside.
|
|
44
|
+
* @internal
|
|
45
|
+
*/
|
|
46
|
+
private readonly _frontier;
|
|
47
47
|
constructor(opts: {
|
|
48
48
|
harness: AgentHarnessContract;
|
|
49
49
|
parent?: Context;
|
|
@@ -59,6 +59,14 @@ export declare class ContextImpl implements Context<ContextMemory> {
|
|
|
59
59
|
itemSchemas?: ItemSchemaRegistry;
|
|
60
60
|
cwdState?: CwdState;
|
|
61
61
|
_broadcaster?: EventBroadcaster;
|
|
62
|
+
/**
|
|
63
|
+
* Pre-chosen context id. When set, the ContextImpl adopts this id instead
|
|
64
|
+
* of generating a fresh UUID. Used by `executeSpawn` so the child's
|
|
65
|
+
* `ctx.id` matches the `executionId` keyed into the layer-state store —
|
|
66
|
+
* otherwise writes via `ctx.memory[layerId].state` land on one id while
|
|
67
|
+
* spawn's `onReturn` reads from another, silently losing the update.
|
|
68
|
+
*/
|
|
69
|
+
id?: string;
|
|
62
70
|
});
|
|
63
71
|
get elapsed(): number;
|
|
64
72
|
get aborted(): boolean;
|
|
@@ -77,4 +85,26 @@ export declare class ContextImpl implements Context<ContextMemory> {
|
|
|
77
85
|
get completionValue(): unknown;
|
|
78
86
|
get abortReason(): string | undefined;
|
|
79
87
|
abort(reason?: string): void;
|
|
88
|
+
/**
|
|
89
|
+
* @internal
|
|
90
|
+
* Push a frame onto the execution frontier. Called by `execute()` at the
|
|
91
|
+
* top of every step dispatch so that the frontier reflects exactly the
|
|
92
|
+
* stack of steps currently in-flight on this context.
|
|
93
|
+
*/
|
|
94
|
+
enterStep(frame: FrontierFrame): void;
|
|
95
|
+
/**
|
|
96
|
+
* @internal
|
|
97
|
+
* Pop the top frame. Called when a step resolves (success or failure)
|
|
98
|
+
* so that the frontier unwinds cleanly. The value of `expectedStepId`
|
|
99
|
+
* is used as a consistency check — if it does not match the top frame
|
|
100
|
+
* the pop is still performed, but a best-effort warning is surfaced to
|
|
101
|
+
* stderr rather than swallowed silently.
|
|
102
|
+
*/
|
|
103
|
+
leaveStep(expectedStepId: string): void;
|
|
104
|
+
/**
|
|
105
|
+
* @internal
|
|
106
|
+
* Return a defensive copy of the current frontier. Consumed by the
|
|
107
|
+
* checkpoint writer — see `AgentHarness.checkpoint`.
|
|
108
|
+
*/
|
|
109
|
+
serialiseFrontier(): FrontierFrame[];
|
|
80
110
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { buildContextMemory } from '
|
|
2
|
-
import { defaultItemSchemaRegistry } from '../schemas/item';
|
|
1
|
+
import { buildContextMemory, defaultItemSchemaRegistry } from './context-deps';
|
|
3
2
|
import { ItemLogImpl } from './item-log-impl';
|
|
4
3
|
const EMPTY_MEMORY = Object.freeze({});
|
|
5
4
|
class NoopSpan {
|
|
@@ -39,7 +38,8 @@ export class ContextImpl {
|
|
|
39
38
|
/**
|
|
40
39
|
* Shared channel store for cross-context communication. Inherited by
|
|
41
40
|
* `fork` / `spawn` children so channels published by a sibling are visible
|
|
42
|
-
* to peers — see `
|
|
41
|
+
* to peers — see `executeFork` and `executeSpawn` in `interpreter/execute-action.ts`
|
|
42
|
+
* and `interpreter/execute-control.ts`.
|
|
43
43
|
* @internal
|
|
44
44
|
*/
|
|
45
45
|
channelStore;
|
|
@@ -49,8 +49,17 @@ export class ContextImpl {
|
|
|
49
49
|
_aborted = false;
|
|
50
50
|
_abortReason;
|
|
51
51
|
_memory;
|
|
52
|
+
/**
|
|
53
|
+
* Stack of steps currently in flight on this context, most-recent last.
|
|
54
|
+
* Pushed by `enterStep` at the top of `execute()` and popped by
|
|
55
|
+
* `leaveStep` when the step resolves (success or failure). The harness'
|
|
56
|
+
* checkpoint writer serialises this stack as the execution frontier so
|
|
57
|
+
* a restart can identify which step the context was paused inside.
|
|
58
|
+
* @internal
|
|
59
|
+
*/
|
|
60
|
+
_frontier = [];
|
|
52
61
|
constructor(opts) {
|
|
53
|
-
this.id = crypto.randomUUID();
|
|
62
|
+
this.id = opts.id ?? crypto.randomUUID();
|
|
54
63
|
this._createdAt = Date.now();
|
|
55
64
|
this.harness = opts.harness;
|
|
56
65
|
this.state = opts.state ?? {};
|
|
@@ -137,4 +146,42 @@ export class ContextImpl {
|
|
|
137
146
|
this._aborted = true;
|
|
138
147
|
this._abortReason = reason;
|
|
139
148
|
}
|
|
149
|
+
/**
|
|
150
|
+
* @internal
|
|
151
|
+
* Push a frame onto the execution frontier. Called by `execute()` at the
|
|
152
|
+
* top of every step dispatch so that the frontier reflects exactly the
|
|
153
|
+
* stack of steps currently in-flight on this context.
|
|
154
|
+
*/
|
|
155
|
+
enterStep(frame) {
|
|
156
|
+
this._frontier.push(frame);
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* @internal
|
|
160
|
+
* Pop the top frame. Called when a step resolves (success or failure)
|
|
161
|
+
* so that the frontier unwinds cleanly. The value of `expectedStepId`
|
|
162
|
+
* is used as a consistency check — if it does not match the top frame
|
|
163
|
+
* the pop is still performed, but a best-effort warning is surfaced to
|
|
164
|
+
* stderr rather than swallowed silently.
|
|
165
|
+
*/
|
|
166
|
+
leaveStep(expectedStepId) {
|
|
167
|
+
const top = this._frontier[this._frontier.length - 1];
|
|
168
|
+
if (top && top.stepId !== expectedStepId) {
|
|
169
|
+
// A mismatch indicates bookkeeping drift. We unwind best-effort and
|
|
170
|
+
// let the caller observe via `serialiseFrontier()` if needed.
|
|
171
|
+
console.warn(`ContextImpl.leaveStep: expected "${expectedStepId}" on top of frontier but saw "${top.stepId}".`);
|
|
172
|
+
}
|
|
173
|
+
this._frontier.pop();
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* @internal
|
|
177
|
+
* Return a defensive copy of the current frontier. Consumed by the
|
|
178
|
+
* checkpoint writer — see `AgentHarness.checkpoint`.
|
|
179
|
+
*/
|
|
180
|
+
serialiseFrontier() {
|
|
181
|
+
return this._frontier.map((frame) => ({
|
|
182
|
+
stepId: frame.stepId,
|
|
183
|
+
input: frame.input,
|
|
184
|
+
state: frame.state,
|
|
185
|
+
}));
|
|
186
|
+
}
|
|
140
187
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type { Channel } from '../types/channel';
|
|
2
|
+
export type { FrontierFrame } from '../types/checkpoint';
|
|
3
|
+
export type { StepMeta, TokenUsage } from '../types/common';
|
|
4
|
+
export type { Context, CwdState } from '../types/context';
|
|
5
|
+
export type { ItemLog } from '../types/context-parts/item-log';
|
|
6
|
+
export type { LastLayerUsage } from '../types/context-parts/layer-usage';
|
|
7
|
+
export type { FsAdapter } from '../types/fs-adapter';
|
|
8
|
+
export type { Item } from '../types/items';
|
|
9
|
+
export type { ContextMemory, MemoryLayer } from '../types/memory';
|
|
10
|
+
export type { Span } from '../types/observability';
|
|
11
|
+
export type { AgentHarnessContract } from '../types/runtime';
|
|
12
|
+
export type { Tool } from '../types/tool';
|
|
13
|
+
export type { ChannelStore } from './channel-store';
|
|
14
|
+
export type { EventBroadcaster } from './event-broadcaster';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,14 +1,62 @@
|
|
|
1
1
|
import type { DetachedHandle } from '../types/detached';
|
|
2
2
|
import { DetachedStatus } from '../types/detached';
|
|
3
|
+
import type { SubprocessAdapter, SubprocessHandle } from '../types/subprocess-adapter';
|
|
4
|
+
interface DetachedHandleOpts {
|
|
5
|
+
/** Id surfaced to callers — usually the execution id (childCtx.id in
|
|
6
|
+
* `detachedSpawn`) so consumers can correlate it with their own state. */
|
|
7
|
+
id: string;
|
|
8
|
+
/** Step id — used when the adapter surfaces a generic failure and we need
|
|
9
|
+
* to produce a `NoeticError` with a meaningful `stepId`. */
|
|
10
|
+
stepId: string;
|
|
11
|
+
/** Adapter that produced the handle. */
|
|
12
|
+
adapter: SubprocessAdapter;
|
|
13
|
+
/**
|
|
14
|
+
* Promise that resolves to the adapter-assigned handle. `detachedSpawn`
|
|
15
|
+
* passes the in-flight `adapter.spawn(request)` promise here so `.await()`
|
|
16
|
+
* is reachable even before the spawn itself has settled.
|
|
17
|
+
*/
|
|
18
|
+
spawnPromise: Promise<SubprocessHandle>;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* @public
|
|
22
|
+
* Thin wrapper over a `SubprocessHandle` that implements the `DetachedHandle`
|
|
23
|
+
* contract. Polls the adapter until the handle reaches a terminal status,
|
|
24
|
+
* then reads the result (or error) off `handle.metadata`.
|
|
25
|
+
*
|
|
26
|
+
* The polling cadence starts at 10ms and ramps to 100ms after the first
|
|
27
|
+
* second — responsive for short-lived in-memory steps without burning cycles
|
|
28
|
+
* on long-running ones.
|
|
29
|
+
*/
|
|
3
30
|
export declare class DetachedHandleImpl<O> implements DetachedHandle<O> {
|
|
4
31
|
readonly id: string;
|
|
32
|
+
private readonly _stepId;
|
|
33
|
+
private readonly _adapter;
|
|
34
|
+
private readonly _spawnPromise;
|
|
35
|
+
private readonly _startTime;
|
|
5
36
|
private _status;
|
|
6
37
|
private _result;
|
|
7
38
|
private _error;
|
|
8
|
-
private
|
|
9
|
-
constructor(
|
|
39
|
+
private _settlementPromise;
|
|
40
|
+
constructor(opts: DetachedHandleOpts);
|
|
10
41
|
get status(): DetachedStatus;
|
|
11
42
|
get result(): O | undefined;
|
|
12
43
|
get error(): string | undefined;
|
|
44
|
+
/**
|
|
45
|
+
* Wait for the underlying handle to settle, up to an optional timeout.
|
|
46
|
+
* On settlement, the cached status/result/error are updated before
|
|
47
|
+
* returning — so a caller that inspects `status` after `await()` resolves
|
|
48
|
+
* observes the final value.
|
|
49
|
+
*/
|
|
13
50
|
await(timeout?: number): Promise<O>;
|
|
51
|
+
/**
|
|
52
|
+
* Start (or return the cached) polling promise that resolves on the first
|
|
53
|
+
* terminal status the adapter reports for this handle.
|
|
54
|
+
*
|
|
55
|
+
* A single settlement promise is shared across all `.await()` callers so
|
|
56
|
+
* repeated calls don't spawn parallel polling loops.
|
|
57
|
+
*/
|
|
58
|
+
private getOrStartSettlement;
|
|
59
|
+
private pollUntilSettled;
|
|
60
|
+
private finalise;
|
|
14
61
|
}
|
|
62
|
+
export {};
|
|
@@ -1,19 +1,125 @@
|
|
|
1
1
|
import { NoeticErrorImpl } from '../errors/noetic-error';
|
|
2
2
|
import { DetachedStatus } from '../types/detached';
|
|
3
|
+
import { frameworkCast } from '../util/framework-cast';
|
|
4
|
+
//#endregion
|
|
5
|
+
//#region Helpers
|
|
6
|
+
const INITIAL_POLL_MS = 10;
|
|
7
|
+
const MAX_POLL_MS = 100;
|
|
8
|
+
const POLL_RAMP_AFTER_MS = 1_000;
|
|
9
|
+
/** Upper bound on microtask yields before falling back to timer-based
|
|
10
|
+
* polling. Chosen empirically: in-memory step bodies settle within a
|
|
11
|
+
* handful of microtasks, and 64 gives plenty of headroom for chained
|
|
12
|
+
* awaits inside complex step trees without busy-spinning. */
|
|
13
|
+
const MAX_MICROTASK_YIELDS = 64;
|
|
14
|
+
/** Grace period before treating persistent null `adapter.get(handleId)`
|
|
15
|
+
* results as an eviction. Tolerates transient nulls from adapters that
|
|
16
|
+
* register the handle asynchronously relative to the spawn promise
|
|
17
|
+
* settling, but bounds the worst case so a corrupt adapter doesn't
|
|
18
|
+
* produce an infinite poll. */
|
|
19
|
+
const HANDLE_EVICTED_GRACE_MS = 500;
|
|
20
|
+
/**
|
|
21
|
+
* Yield control to the timer queue so the adapter has a chance to
|
|
22
|
+
* transition the handle before we issue the next `adapter.get()` call.
|
|
23
|
+
* Using a timer (even 0ms) ensures we don't spin-lock when the adapter
|
|
24
|
+
* schedules its completion on a later microtask.
|
|
25
|
+
*/
|
|
26
|
+
function sleep(ms) {
|
|
27
|
+
if (ms <= 0) {
|
|
28
|
+
return Promise.resolve();
|
|
29
|
+
}
|
|
30
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
31
|
+
}
|
|
32
|
+
function isTerminalStatus(status) {
|
|
33
|
+
return (status === 'completed' || status === 'failed' || status === 'stopped' || status === 'stale');
|
|
34
|
+
}
|
|
35
|
+
function isRecord(value) {
|
|
36
|
+
return typeof value === 'object' && value !== null;
|
|
37
|
+
}
|
|
38
|
+
function isNoeticErrorPayload(value) {
|
|
39
|
+
return isRecord(value) && typeof value.kind === 'string';
|
|
40
|
+
}
|
|
41
|
+
/** Rehydrate a thrown error from the handle metadata. Preserves the
|
|
42
|
+
* structured NoeticError shape when present so type-guards like
|
|
43
|
+
* `isNoeticError` keep working on the consumer side. */
|
|
44
|
+
function rehydrateError(payload, stepId) {
|
|
45
|
+
if (!payload) {
|
|
46
|
+
return new NoeticErrorImpl({
|
|
47
|
+
kind: 'step_failed',
|
|
48
|
+
stepId,
|
|
49
|
+
cause: new Error('Detached spawn failed without an error payload'),
|
|
50
|
+
retriesExhausted: false,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
if (isNoeticErrorPayload(payload.noeticError)) {
|
|
54
|
+
return new NoeticErrorImpl(payload.noeticError);
|
|
55
|
+
}
|
|
56
|
+
const err = new Error(payload.message);
|
|
57
|
+
if (payload.name) {
|
|
58
|
+
err.name = payload.name;
|
|
59
|
+
}
|
|
60
|
+
if (payload.stack) {
|
|
61
|
+
err.stack = payload.stack;
|
|
62
|
+
}
|
|
63
|
+
return err;
|
|
64
|
+
}
|
|
65
|
+
function extractResult(metadata) {
|
|
66
|
+
if (!metadata || metadata.result === undefined) {
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
return frameworkCast(metadata.result);
|
|
70
|
+
}
|
|
71
|
+
function extractError(metadata) {
|
|
72
|
+
if (!metadata || metadata.error === undefined) {
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
const raw = metadata.error;
|
|
76
|
+
if (!isRecord(raw)) {
|
|
77
|
+
return {
|
|
78
|
+
message: String(raw),
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
const message = typeof raw.message === 'string' ? raw.message : 'unknown error';
|
|
82
|
+
const name = typeof raw.name === 'string' ? raw.name : undefined;
|
|
83
|
+
const stack = typeof raw.stack === 'string' ? raw.stack : undefined;
|
|
84
|
+
return {
|
|
85
|
+
message,
|
|
86
|
+
name,
|
|
87
|
+
stack,
|
|
88
|
+
noeticError: raw.noeticError,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
//#endregion
|
|
3
92
|
//#region DetachedHandleImpl
|
|
93
|
+
/**
|
|
94
|
+
* @public
|
|
95
|
+
* Thin wrapper over a `SubprocessHandle` that implements the `DetachedHandle`
|
|
96
|
+
* contract. Polls the adapter until the handle reaches a terminal status,
|
|
97
|
+
* then reads the result (or error) off `handle.metadata`.
|
|
98
|
+
*
|
|
99
|
+
* The polling cadence starts at 10ms and ramps to 100ms after the first
|
|
100
|
+
* second — responsive for short-lived in-memory steps without burning cycles
|
|
101
|
+
* on long-running ones.
|
|
102
|
+
*/
|
|
4
103
|
export class DetachedHandleImpl {
|
|
5
104
|
id;
|
|
105
|
+
_stepId;
|
|
106
|
+
_adapter;
|
|
107
|
+
_spawnPromise;
|
|
108
|
+
_startTime;
|
|
6
109
|
_status = DetachedStatus.Running;
|
|
7
110
|
_result;
|
|
8
111
|
_error;
|
|
9
|
-
|
|
10
|
-
constructor(
|
|
11
|
-
this.id = id;
|
|
12
|
-
this.
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
112
|
+
_settlementPromise;
|
|
113
|
+
constructor(opts) {
|
|
114
|
+
this.id = opts.id;
|
|
115
|
+
this._stepId = opts.stepId;
|
|
116
|
+
this._adapter = opts.adapter;
|
|
117
|
+
this._spawnPromise = opts.spawnPromise;
|
|
118
|
+
this._startTime = Date.now();
|
|
119
|
+
// Observe spawn failure eagerly so `.error` is populated even if the
|
|
120
|
+
// caller never invokes `.await()`. We intentionally swallow the
|
|
121
|
+
// rejection here — `.await()` surfaces it to the caller.
|
|
122
|
+
this._spawnPromise.catch((err) => {
|
|
17
123
|
this._status = DetachedStatus.Failed;
|
|
18
124
|
this._error = err instanceof Error ? err.message : String(err);
|
|
19
125
|
});
|
|
@@ -27,16 +133,23 @@ export class DetachedHandleImpl {
|
|
|
27
133
|
get error() {
|
|
28
134
|
return this._error;
|
|
29
135
|
}
|
|
136
|
+
/**
|
|
137
|
+
* Wait for the underlying handle to settle, up to an optional timeout.
|
|
138
|
+
* On settlement, the cached status/result/error are updated before
|
|
139
|
+
* returning — so a caller that inspects `status` after `await()` resolves
|
|
140
|
+
* observes the final value.
|
|
141
|
+
*/
|
|
30
142
|
async await(timeout) {
|
|
143
|
+
const settlement = this.getOrStartSettlement();
|
|
31
144
|
if (timeout === undefined || timeout <= 0) {
|
|
32
|
-
return
|
|
145
|
+
return settlement;
|
|
33
146
|
}
|
|
34
147
|
let timerId;
|
|
35
148
|
const timeoutPromise = new Promise((_resolve, reject) => {
|
|
36
149
|
timerId = setTimeout(() => {
|
|
37
150
|
reject(new NoeticErrorImpl({
|
|
38
151
|
kind: 'step_failed',
|
|
39
|
-
stepId: this.
|
|
152
|
+
stepId: this._stepId,
|
|
40
153
|
cause: new Error(`Detached spawn timed out after ${timeout}ms`),
|
|
41
154
|
retriesExhausted: false,
|
|
42
155
|
}));
|
|
@@ -44,13 +157,104 @@ export class DetachedHandleImpl {
|
|
|
44
157
|
});
|
|
45
158
|
try {
|
|
46
159
|
return await Promise.race([
|
|
47
|
-
|
|
160
|
+
settlement,
|
|
48
161
|
timeoutPromise,
|
|
49
162
|
]);
|
|
50
163
|
}
|
|
51
164
|
finally {
|
|
52
|
-
|
|
165
|
+
if (timerId !== undefined) {
|
|
166
|
+
clearTimeout(timerId);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Start (or return the cached) polling promise that resolves on the first
|
|
172
|
+
* terminal status the adapter reports for this handle.
|
|
173
|
+
*
|
|
174
|
+
* A single settlement promise is shared across all `.await()` callers so
|
|
175
|
+
* repeated calls don't spawn parallel polling loops.
|
|
176
|
+
*/
|
|
177
|
+
getOrStartSettlement() {
|
|
178
|
+
if (this._settlementPromise) {
|
|
179
|
+
return this._settlementPromise;
|
|
180
|
+
}
|
|
181
|
+
this._settlementPromise = this.pollUntilSettled();
|
|
182
|
+
return this._settlementPromise;
|
|
183
|
+
}
|
|
184
|
+
async pollUntilSettled() {
|
|
185
|
+
// Wait for the spawn itself to succeed before we start polling —
|
|
186
|
+
// otherwise we'd be polling with an undefined handle id.
|
|
187
|
+
const initialHandle = await this._spawnPromise;
|
|
188
|
+
if (isTerminalStatus(initialHandle.status)) {
|
|
189
|
+
return this.finalise(initialHandle);
|
|
190
|
+
}
|
|
191
|
+
// Track when the adapter persistently returns null for this handle.
|
|
192
|
+
// Transient nulls are tolerated for `HANDLE_EVICTED_GRACE_MS`; after
|
|
193
|
+
// that we raise `handle_evicted` instead of looping forever. A
|
|
194
|
+
// non-null observation resets the grace window.
|
|
195
|
+
let firstNullAt = null;
|
|
196
|
+
const observeNull = () => {
|
|
197
|
+
if (firstNullAt === null) {
|
|
198
|
+
firstNullAt = Date.now();
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
if (Date.now() - firstNullAt >= HANDLE_EVICTED_GRACE_MS) {
|
|
202
|
+
throw new NoeticErrorImpl({
|
|
203
|
+
kind: 'handle_evicted',
|
|
204
|
+
handleId: initialHandle.id,
|
|
205
|
+
stepId: this._stepId,
|
|
206
|
+
gracePeriodMs: HANDLE_EVICTED_GRACE_MS,
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
const observeHandle = (h) => {
|
|
211
|
+
if (h === null) {
|
|
212
|
+
observeNull();
|
|
213
|
+
return null;
|
|
214
|
+
}
|
|
215
|
+
firstNullAt = null;
|
|
216
|
+
return h;
|
|
217
|
+
};
|
|
218
|
+
// Fast path: yield through the microtask queue first. The in-memory
|
|
219
|
+
// adapter schedules completion on a microtask, so a handful of yields
|
|
220
|
+
// typically resolves the handle in sub-millisecond time. This keeps the
|
|
221
|
+
// interpreter's "route through adapter" overhead negligible.
|
|
222
|
+
for (let i = 0; i < MAX_MICROTASK_YIELDS; i++) {
|
|
223
|
+
const handle = observeHandle(await this._adapter.get(initialHandle.id));
|
|
224
|
+
if (handle && isTerminalStatus(handle.status)) {
|
|
225
|
+
return this.finalise(handle);
|
|
226
|
+
}
|
|
227
|
+
await Promise.resolve();
|
|
228
|
+
}
|
|
229
|
+
// Slow path: fall back to timer-based polling for genuinely long-running
|
|
230
|
+
// handles (out-of-process adapters, async work that doesn't resolve on
|
|
231
|
+
// the microtask queue).
|
|
232
|
+
let delay = INITIAL_POLL_MS;
|
|
233
|
+
for (;;) {
|
|
234
|
+
const handle = observeHandle(await this._adapter.get(initialHandle.id));
|
|
235
|
+
if (handle && isTerminalStatus(handle.status)) {
|
|
236
|
+
return this.finalise(handle);
|
|
237
|
+
}
|
|
238
|
+
await sleep(delay);
|
|
239
|
+
if (Date.now() - this._startTime >= POLL_RAMP_AFTER_MS) {
|
|
240
|
+
delay = MAX_POLL_MS;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
finalise(handle) {
|
|
245
|
+
const metadata = handle.metadata;
|
|
246
|
+
if (handle.status === 'completed') {
|
|
247
|
+
const value = extractResult(metadata);
|
|
248
|
+
this._status = DetachedStatus.Completed;
|
|
249
|
+
this._result = value;
|
|
250
|
+
return frameworkCast(value);
|
|
53
251
|
}
|
|
252
|
+
// Failed / stopped / stale — all map to Failed from the caller's view.
|
|
253
|
+
const errorPayload = extractError(metadata);
|
|
254
|
+
const err = rehydrateError(errorPayload, this._stepId);
|
|
255
|
+
this._status = DetachedStatus.Failed;
|
|
256
|
+
this._error = err.message;
|
|
257
|
+
throw err;
|
|
54
258
|
}
|
|
55
259
|
}
|
|
56
260
|
//#endregion
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { CheckpointSnapshot } from '../../types/checkpoint';
|
|
2
|
+
import type { StorageAdapter } from '../../types/memory';
|
|
3
|
+
export declare const CheckpointKeys: {
|
|
4
|
+
readonly ExecPrefix: "execution:";
|
|
5
|
+
readonly SnapshotSuffix: ":snapshot";
|
|
6
|
+
readonly FrontierSuffix: ":frontier";
|
|
7
|
+
readonly LayersSuffix: ":layers:";
|
|
8
|
+
readonly CwdSuffix: ":cwd";
|
|
9
|
+
readonly AskUserSuffix: ":askUser";
|
|
10
|
+
readonly ItemLogSuffix: ":itemLog";
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* @public
|
|
14
|
+
* Typed wrapper around a `StorageAdapter` that owns the key layout for
|
|
15
|
+
* checkpoint snapshots and validates every read with the canonical Zod
|
|
16
|
+
* schema.
|
|
17
|
+
*
|
|
18
|
+
* Corruption or schema-version drift is surfaced as `NoeticConfigError`
|
|
19
|
+
* (`code === 'CHECKPOINT_SCHEMA_MISMATCH'`) so callers can discard the
|
|
20
|
+
* offending snapshot without crashing the host.
|
|
21
|
+
*/
|
|
22
|
+
export interface CheckpointStore {
|
|
23
|
+
/** Persist a snapshot. Later calls for the same `executionId` overwrite. */
|
|
24
|
+
save(snapshot: CheckpointSnapshot): Promise<void>;
|
|
25
|
+
/** Load the snapshot for an execution, or `null` if none is recorded. */
|
|
26
|
+
load(executionId: string): Promise<CheckpointSnapshot | null>;
|
|
27
|
+
/** List every `executionId` that has a persisted snapshot. */
|
|
28
|
+
list(): Promise<ReadonlyArray<{
|
|
29
|
+
executionId: string;
|
|
30
|
+
}>>;
|
|
31
|
+
/** Remove the snapshot for `executionId`. No-op when the key is absent. */
|
|
32
|
+
clear(executionId: string): Promise<void>;
|
|
33
|
+
}
|
|
34
|
+
/** @public Options for `createCheckpointStore`. */
|
|
35
|
+
export interface CreateCheckpointStoreOptions {
|
|
36
|
+
storage: StorageAdapter;
|
|
37
|
+
}
|
|
38
|
+
export declare function createCheckpointStore(options: CreateCheckpointStoreOptions): CheckpointStore;
|