@zenera/neo 1.1.11 → 1.1.12
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/README.md +3 -3
- package/dist/agent.d.ts +8 -7
- package/dist/agent.js +15 -8
- package/dist/architecture.d.ts +7 -5
- package/dist/architecture.js +20 -12
- package/dist/index.d.ts +12 -2
- package/dist/index.js +12 -2
- package/dist/inspect/client.d.ts +1 -1
- package/dist/inspect/client.js +42 -26
- package/dist/kernel.d.ts +1 -1
- package/dist/kernel.js +40 -23
- package/dist/memory/files.d.ts +24 -0
- package/dist/memory/files.js +85 -0
- package/dist/memory/graph.d.ts +56 -0
- package/dist/memory/graph.js +159 -0
- package/dist/memory/index.d.ts +93 -0
- package/dist/memory/index.js +357 -0
- package/dist/memory/instructions.d.ts +15 -0
- package/dist/memory/instructions.js +103 -0
- package/dist/memory/page.d.ts +8 -0
- package/dist/memory/page.js +797 -0
- package/dist/memory/recall.d.ts +35 -0
- package/dist/memory/recall.js +161 -0
- package/dist/memory/render.d.ts +10 -0
- package/dist/memory/render.js +228 -0
- package/dist/memory/report.d.ts +57 -0
- package/dist/memory/report.js +113 -0
- package/dist/memory/store.d.ts +49 -0
- package/dist/memory/store.js +226 -0
- package/dist/memory/tools.d.ts +11 -0
- package/dist/memory/tools.js +310 -0
- package/dist/memory/types.d.ts +192 -0
- package/dist/memory/types.js +105 -0
- package/dist/memory/vectors.d.ts +29 -0
- package/dist/memory/vectors.js +152 -0
- package/dist/project/config.d.ts +49 -1
- package/dist/project/config.js +63 -0
- package/dist/project/index.d.ts +2 -2
- package/dist/project/index.js +1 -1
- package/dist/project/load.d.ts +16 -2
- package/dist/project/load.js +67 -1
- package/dist/runner.d.ts +4 -2
- package/dist/runner.js +29 -30
- package/dist/services.d.ts +23 -6
- package/dist/services.js +25 -15
- package/dist/tools/workspace.js +195 -17
- package/dist/trajectory.d.ts +14 -12
- package/dist/types.d.ts +5 -5
- package/dist/types.js +3 -3
- package/package.json +2 -5
- package/dist/memory-stores/factory.d.ts +0 -15
- package/dist/memory-stores/factory.js +0 -29
- package/dist/memory-stores/file.d.ts +0 -37
- package/dist/memory-stores/file.js +0 -174
- package/dist/memory-stores/in-memory.d.ts +0 -17
- package/dist/memory-stores/in-memory.js +0 -80
- package/dist/memory-stores/index.d.ts +0 -4
- package/dist/memory-stores/index.js +0 -5
- package/dist/memory.d.ts +0 -115
- package/dist/memory.js +0 -213
package/dist/project/load.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Agent, AgentRegistry } from '../agent.ts';
|
|
2
2
|
import type { Embedder } from '../embedding.ts';
|
|
3
3
|
import { RunStream } from '../events.ts';
|
|
4
|
-
import
|
|
4
|
+
import { MemoryIndex } from '../memory/index.ts';
|
|
5
5
|
import { ModelRegistry, type EmbeddingRef, type ModelRef, type ProviderSpec } from '../models/factory.ts';
|
|
6
6
|
import type { PayloadStore } from '../payload.ts';
|
|
7
7
|
import { AgentRunner, type RunOptions, type RunnerOptions } from '../runner.ts';
|
|
@@ -54,7 +54,9 @@ export interface ProjectOptions<TCtx = unknown> {
|
|
|
54
54
|
* project never reaches the network.
|
|
55
55
|
*/
|
|
56
56
|
registry?: ModelRegistry;
|
|
57
|
-
memory?:
|
|
57
|
+
memory?: MemoryIndex;
|
|
58
|
+
/** turns an agent-visible path into a host path, so files can be remembered */
|
|
59
|
+
resolveFile?: (path: string) => string;
|
|
58
60
|
payloads?: PayloadStore;
|
|
59
61
|
/** extra providers merged with the ones the project declares */
|
|
60
62
|
skills?: SkillProvider[];
|
|
@@ -99,6 +101,7 @@ interface ProjectParts<TCtx> {
|
|
|
99
101
|
skillProviders: SkillProvider[];
|
|
100
102
|
assets: string | undefined;
|
|
101
103
|
models: ModelRegistry;
|
|
104
|
+
memory: MemoryIndex | undefined;
|
|
102
105
|
embedders: (ref: string | undefined, where: string) => Embedder | undefined;
|
|
103
106
|
options: ProjectOptions<TCtx>;
|
|
104
107
|
}
|
|
@@ -129,7 +132,11 @@ export declare class AgentProject<TCtx = unknown> {
|
|
|
129
132
|
readonly assets: string | undefined;
|
|
130
133
|
/** the providers this project declared, and the clients behind them */
|
|
131
134
|
readonly models: ModelRegistry;
|
|
135
|
+
/** the one memory graph, when this project has one */
|
|
136
|
+
readonly memory: MemoryIndex | undefined;
|
|
132
137
|
constructor(parts: ProjectParts<TCtx>);
|
|
138
|
+
/** Releases the memory lock. A project that holds no memory need not be closed. */
|
|
139
|
+
close(): void;
|
|
133
140
|
get agents(): readonly Agent<TCtx>[];
|
|
134
141
|
/**
|
|
135
142
|
* A declared vectoriser, memoized. Named or not: with no argument this is
|
|
@@ -153,6 +160,13 @@ export declare class AgentProject<TCtx = unknown> {
|
|
|
153
160
|
* for, and only pay for it if an agent actually reaches for it.
|
|
154
161
|
*/
|
|
155
162
|
export declare function projectRegistry<TCtx>(config: ProjectConfig, opts?: ProjectOptions<TCtx>): ModelRegistry;
|
|
163
|
+
/**
|
|
164
|
+
* Where this project's memory lives, or `undefined` when it has none. Shared
|
|
165
|
+
* with the front end, which has to mount the same directory into the sandbox:
|
|
166
|
+
* two answers to this question would mean `/memory` pointing somewhere the
|
|
167
|
+
* graph is not.
|
|
168
|
+
*/
|
|
169
|
+
export declare function memoryDir(root: string, config: ProjectConfig): string | undefined;
|
|
156
170
|
/**
|
|
157
171
|
* Where each skill directory appears in the agent's namespace.
|
|
158
172
|
*
|
package/dist/project/load.js
CHANGED
|
@@ -2,6 +2,8 @@ import { existsSync, readFileSync, statSync } from 'node:fs';
|
|
|
2
2
|
import { basename, join } from 'node:path';
|
|
3
3
|
import { Agent, AgentRegistry } from "../agent.js";
|
|
4
4
|
import { RunStream } from "../events.js";
|
|
5
|
+
import { MemoryIndex } from "../memory/index.js";
|
|
6
|
+
import { MemoryStore } from "../memory/store.js";
|
|
5
7
|
import { ModelRegistry, } from "../models/factory.js";
|
|
6
8
|
import { promptFile } from "../prompt.js";
|
|
7
9
|
import { AgentRunner } from "../runner.js";
|
|
@@ -59,6 +61,7 @@ export async function loadProject(dir, opts = {}) {
|
|
|
59
61
|
handoffs: spec.handoffs,
|
|
60
62
|
skills: bindingFor(spec, providers),
|
|
61
63
|
fork: forkFor(spec),
|
|
64
|
+
memory: memoryFor(spec),
|
|
62
65
|
});
|
|
63
66
|
}
|
|
64
67
|
validate(config, registry, providers, catalogs, models);
|
|
@@ -66,12 +69,14 @@ export async function loadProject(dir, opts = {}) {
|
|
|
66
69
|
// The default is resolved here rather than on first use, so a broken
|
|
67
70
|
// `embedding:` fails at load like a broken `model:` does.
|
|
68
71
|
embedders(config.embedding, 'embedding');
|
|
72
|
+
const memory = opts.memory ?? (await openMemory(root, config, embedders));
|
|
69
73
|
return new AgentProject({
|
|
70
74
|
root,
|
|
71
75
|
source,
|
|
72
76
|
config,
|
|
73
77
|
entry: entrypoint(config),
|
|
74
78
|
registry,
|
|
79
|
+
memory,
|
|
75
80
|
skillProviders: providers,
|
|
76
81
|
assets,
|
|
77
82
|
models,
|
|
@@ -105,6 +110,8 @@ export class AgentProject {
|
|
|
105
110
|
assets;
|
|
106
111
|
/** the providers this project declared, and the clients behind them */
|
|
107
112
|
models;
|
|
113
|
+
/** the one memory graph, when this project has one */
|
|
114
|
+
memory;
|
|
108
115
|
#embedders;
|
|
109
116
|
#options;
|
|
110
117
|
#runner;
|
|
@@ -117,9 +124,14 @@ export class AgentProject {
|
|
|
117
124
|
this.skillProviders = parts.skillProviders;
|
|
118
125
|
this.assets = parts.assets;
|
|
119
126
|
this.models = parts.models;
|
|
127
|
+
this.memory = parts.memory;
|
|
120
128
|
this.#embedders = parts.embedders;
|
|
121
129
|
this.#options = parts.options;
|
|
122
130
|
}
|
|
131
|
+
/** Releases the memory lock. A project that holds no memory need not be closed. */
|
|
132
|
+
close() {
|
|
133
|
+
this.memory?.store.release();
|
|
134
|
+
}
|
|
123
135
|
get agents() {
|
|
124
136
|
return [...this.registry.agents.values()];
|
|
125
137
|
}
|
|
@@ -151,7 +163,8 @@ export class AgentProject {
|
|
|
151
163
|
#build(overrides = {}) {
|
|
152
164
|
const runner = new AgentRunner({
|
|
153
165
|
payloads: this.#options.payloads,
|
|
154
|
-
memory: this
|
|
166
|
+
memory: this.memory,
|
|
167
|
+
resolveFile: this.#options.resolveFile,
|
|
155
168
|
skills: [...this.skillProviders],
|
|
156
169
|
...overrides,
|
|
157
170
|
});
|
|
@@ -315,6 +328,59 @@ function forkFor(spec) {
|
|
|
315
328
|
}
|
|
316
329
|
return spec.fork === true ? {} : spec.fork;
|
|
317
330
|
}
|
|
331
|
+
/**
|
|
332
|
+
* `memory: true` is the whole feature working the obvious way: read and write,
|
|
333
|
+
* and recall before a turn that follows new user input. An agent that has to
|
|
334
|
+
* remember to go looking mostly does not, so auto-recall is on by default and
|
|
335
|
+
* `autoRecall: false` is how you turn it off.
|
|
336
|
+
*/
|
|
337
|
+
function memoryFor(spec) {
|
|
338
|
+
const b = spec.memory;
|
|
339
|
+
if (!b) {
|
|
340
|
+
return undefined;
|
|
341
|
+
}
|
|
342
|
+
const auto = b.autoRecall ?? true;
|
|
343
|
+
return {
|
|
344
|
+
access: b.access,
|
|
345
|
+
sees: b.sees,
|
|
346
|
+
writes: b.writes,
|
|
347
|
+
autoRecall: auto
|
|
348
|
+
? { query: 'last_user_input', limit: auto === true ? 5 : auto.limit }
|
|
349
|
+
: undefined,
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Where this project's memory lives, or `undefined` when it has none. Shared
|
|
354
|
+
* with the front end, which has to mount the same directory into the sandbox:
|
|
355
|
+
* two answers to this question would mean `/memory` pointing somewhere the
|
|
356
|
+
* graph is not.
|
|
357
|
+
*/
|
|
358
|
+
export function memoryDir(root, config) {
|
|
359
|
+
if (!config.memory && !config.agents.some((a) => a.memory)) {
|
|
360
|
+
return undefined;
|
|
361
|
+
}
|
|
362
|
+
return join(root, config.memory?.dir ?? 'memory');
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Opened only when something will use it, so an ordinary project neither
|
|
366
|
+
* creates a directory nor takes a lock. A `memory:` block with no agent bound
|
|
367
|
+
* to it still counts: it is how a project declares the graph `zen memory`
|
|
368
|
+
* inspects between runs.
|
|
369
|
+
*/
|
|
370
|
+
async function openMemory(root, config, embedders) {
|
|
371
|
+
const dir = memoryDir(root, config);
|
|
372
|
+
if (!dir) {
|
|
373
|
+
return undefined;
|
|
374
|
+
}
|
|
375
|
+
const declared = config.memory;
|
|
376
|
+
const embedder = embedders(declared?.embedding ?? config.embedding, 'memory.embedding');
|
|
377
|
+
return new MemoryIndex({
|
|
378
|
+
store: await MemoryStore.open(dir),
|
|
379
|
+
embedder,
|
|
380
|
+
kinds: declared?.kinds,
|
|
381
|
+
relations: declared?.relations,
|
|
382
|
+
});
|
|
383
|
+
}
|
|
318
384
|
function skillProviders(root, config, opts) {
|
|
319
385
|
const declared = skillDirs(root, config);
|
|
320
386
|
if (!declared.length) {
|
package/dist/runner.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { Agent, AgentRegistry, type AgentOptions } from './agent.ts';
|
|
|
3
3
|
import { type Architecture } from './architecture.ts';
|
|
4
4
|
import { RunStream } from './events.ts';
|
|
5
5
|
import { type IdClock } from './ids.ts';
|
|
6
|
-
import type {
|
|
6
|
+
import type { MemoryIndex } from './memory/index.ts';
|
|
7
7
|
import type { Model } from './model.ts';
|
|
8
8
|
import { PayloadResolver, type PayloadStore } from './payload.ts';
|
|
9
9
|
import { Services } from './services.ts';
|
|
@@ -41,7 +41,9 @@ export interface RunnerOptions<TCtx = unknown> {
|
|
|
41
41
|
context?: TCtx;
|
|
42
42
|
services?: Services;
|
|
43
43
|
payloads?: PayloadStore | PayloadResolver;
|
|
44
|
-
memory?:
|
|
44
|
+
memory?: MemoryIndex;
|
|
45
|
+
/** turns an agent-visible path into a host path, so files can be remembered */
|
|
46
|
+
resolveFile?: (path: string) => string;
|
|
45
47
|
skills?: SkillProvider[];
|
|
46
48
|
handoffPolicy?: HandoffPolicy;
|
|
47
49
|
/** renders the nodes a policy selected; defaults to a structural note */
|
package/dist/runner.js
CHANGED
|
@@ -3,7 +3,7 @@ import { describeArchitecture } from "./architecture.js";
|
|
|
3
3
|
import { EventQueue, RunStream, } from "./events.js";
|
|
4
4
|
import { systemClock } from "./ids.js";
|
|
5
5
|
import * as Kernel from "./kernel.js";
|
|
6
|
-
import {
|
|
6
|
+
import { renderRecollection } from "./memory/render.js";
|
|
7
7
|
import { PayloadResolver } from "./payload.js";
|
|
8
8
|
import { Services } from "./services.js";
|
|
9
9
|
import { activeSkillNames } from "./skills.js";
|
|
@@ -76,19 +76,21 @@ export class AgentRunner {
|
|
|
76
76
|
constructor(opts = {}) {
|
|
77
77
|
this.#model = opts.model;
|
|
78
78
|
this.#context = opts.context;
|
|
79
|
+
this.#clock = opts.clock ?? systemClock;
|
|
79
80
|
this.services =
|
|
80
81
|
opts.services ??
|
|
81
82
|
new Services({
|
|
82
83
|
payloads: opts.payloads,
|
|
83
84
|
memory: opts.memory,
|
|
85
|
+
resolveFile: opts.resolveFile,
|
|
84
86
|
skills: opts.skills,
|
|
87
|
+
clock: this.#clock,
|
|
85
88
|
});
|
|
86
89
|
this.#handoffPolicy = opts.handoffPolicy;
|
|
87
90
|
this.#summarizer = opts.summarizer ?? structuralSummarizer;
|
|
88
91
|
this.#joinPolicy = opts.joinPolicy ?? defaultJoinPolicy;
|
|
89
92
|
this.#stream = opts.stream ?? true;
|
|
90
93
|
this.#recordRequests = opts.recordRequests ?? false;
|
|
91
|
-
this.#clock = opts.clock ?? systemClock;
|
|
92
94
|
}
|
|
93
95
|
/** Registers agents; chainable. */
|
|
94
96
|
add(...agents) {
|
|
@@ -387,11 +389,12 @@ export class AgentRunner {
|
|
|
387
389
|
* caching for a marginal gain.
|
|
388
390
|
*/
|
|
389
391
|
async #autoRecall(state, env) {
|
|
390
|
-
const
|
|
391
|
-
const
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
392
|
+
const memory = this.services.memory;
|
|
393
|
+
const binding = this.registry.get(state.agentName).memoryBinding(state.context);
|
|
394
|
+
if (!memory || !binding?.autoRecall || binding.autoRecall.query === 'none') {
|
|
395
|
+
return state;
|
|
396
|
+
}
|
|
397
|
+
if (!shouldRecall(state)) {
|
|
395
398
|
return state;
|
|
396
399
|
}
|
|
397
400
|
const input = Kernel.lastUserInput(state);
|
|
@@ -399,32 +402,28 @@ export class AgentRunner {
|
|
|
399
402
|
return state;
|
|
400
403
|
}
|
|
401
404
|
const parts = await Promise.all(input.content.map((p) => p.type === 'text' ? this.services.payloads.get(p.text) : Promise.resolve('')));
|
|
402
|
-
const
|
|
403
|
-
if (!
|
|
405
|
+
const text = parts.filter(Boolean).join('\n');
|
|
406
|
+
if (!text) {
|
|
404
407
|
return state;
|
|
405
408
|
}
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
if (!hits.length) {
|
|
412
|
-
continue;
|
|
413
|
-
}
|
|
414
|
-
next = await Kernel.applyMemoryEffect(next, {
|
|
415
|
-
kind: 'recall',
|
|
416
|
-
store: b.store,
|
|
417
|
-
scope: b.scope,
|
|
418
|
-
query: { text: query, limit: b.autoRecall?.limit ?? 5 },
|
|
419
|
-
hits: hits.map((h) => ({
|
|
420
|
-
id: h.record.id,
|
|
421
|
-
score: h.score,
|
|
422
|
-
revision: h.record.revision,
|
|
423
|
-
})),
|
|
424
|
-
content: renderMemories(hits),
|
|
425
|
-
}, env);
|
|
409
|
+
const query = { text, limit: binding.autoRecall.limit };
|
|
410
|
+
const rec = await memory.search(query, binding.sees);
|
|
411
|
+
const content = renderRecollection(rec);
|
|
412
|
+
if (!content) {
|
|
413
|
+
return state;
|
|
426
414
|
}
|
|
427
|
-
return
|
|
415
|
+
return Kernel.applyMemoryEffect(state, {
|
|
416
|
+
kind: 'recall',
|
|
417
|
+
query,
|
|
418
|
+
seeds: [...rec.seeds],
|
|
419
|
+
nodes: rec.nodes.map((n) => ({
|
|
420
|
+
id: n.node.id,
|
|
421
|
+
kind: n.node.kind,
|
|
422
|
+
score: n.score,
|
|
423
|
+
})),
|
|
424
|
+
edges: [...rec.edges],
|
|
425
|
+
content,
|
|
426
|
+
}, env);
|
|
428
427
|
}
|
|
429
428
|
/**
|
|
430
429
|
* Failure-tolerant on purpose: an unknown tool, malformed arguments or a
|
package/dist/services.d.ts
CHANGED
|
@@ -1,23 +1,40 @@
|
|
|
1
1
|
import { PayloadResolver, type PayloadStore } from './payload.ts';
|
|
2
|
-
import type
|
|
2
|
+
import { type IdClock } from './ids.ts';
|
|
3
|
+
import type { MemoryIndex } from './memory/index.ts';
|
|
3
4
|
import type { SkillProvider } from './skills.ts';
|
|
4
5
|
/**
|
|
5
|
-
* The I/O the kernel is not allowed to do itself: payload resolution,
|
|
6
|
-
*
|
|
6
|
+
* The I/O the kernel is not allowed to do itself: payload resolution, the
|
|
7
|
+
* memory graph and skill catalogs. Held by the driver (runner or Temporal
|
|
7
8
|
* activity) and handed to the kernel and to tools explicitly, so nothing reads
|
|
8
9
|
* ambient state.
|
|
10
|
+
*
|
|
11
|
+
* There is one memory, not a map of them: an agent sees a slice of the single
|
|
12
|
+
* graph through its `sees` mask, which is what makes a memory shareable
|
|
13
|
+
* between agents at all.
|
|
9
14
|
*/
|
|
10
15
|
export declare class Services {
|
|
11
16
|
#private;
|
|
12
17
|
readonly payloads: PayloadResolver;
|
|
18
|
+
/** the one memory graph, when the project has one */
|
|
19
|
+
readonly memory?: MemoryIndex;
|
|
20
|
+
/**
|
|
21
|
+
* Turns a path the agent can see into a host path, for the one tool that
|
|
22
|
+
* needs it: remembering a file. Supplied by whoever built the workspace,
|
|
23
|
+
* because only it knows the mounts. Without it, files cannot be
|
|
24
|
+
* remembered — which is a refusal, not a crash.
|
|
25
|
+
*/
|
|
26
|
+
readonly resolveFile?: (path: string) => string;
|
|
27
|
+
/** the driver's clock, so a tool that stamps a node stays replayable */
|
|
28
|
+
readonly clock: IdClock;
|
|
13
29
|
constructor(opts?: {
|
|
14
30
|
payloads?: PayloadResolver | PayloadStore;
|
|
15
|
-
memory?:
|
|
31
|
+
memory?: MemoryIndex;
|
|
16
32
|
skills?: SkillProvider[];
|
|
33
|
+
clock?: IdClock;
|
|
34
|
+
resolveFile?: (path: string) => string;
|
|
17
35
|
});
|
|
18
|
-
memoryStore(id: string): MemoryStore;
|
|
19
36
|
skillProvider(id: string): SkillProvider;
|
|
20
|
-
hasMemory(
|
|
37
|
+
hasMemory(): boolean;
|
|
21
38
|
hasSkills(id: string): boolean;
|
|
22
39
|
}
|
|
23
40
|
//# sourceMappingURL=services.d.ts.map
|
package/dist/services.js
CHANGED
|
@@ -1,32 +1,42 @@
|
|
|
1
1
|
import { PayloadResolver } from "./payload.js";
|
|
2
|
+
// The composition root is the one place in the core allowed to name a backend:
|
|
3
|
+
// it has to fall back to something when the caller supplies no store.
|
|
4
|
+
import { systemClock } from "./ids.js";
|
|
2
5
|
import { InMemoryPayloadStore } from "./payload-stores/in-memory.js";
|
|
3
6
|
/**
|
|
4
|
-
* The I/O the kernel is not allowed to do itself: payload resolution,
|
|
5
|
-
*
|
|
7
|
+
* The I/O the kernel is not allowed to do itself: payload resolution, the
|
|
8
|
+
* memory graph and skill catalogs. Held by the driver (runner or Temporal
|
|
6
9
|
* activity) and handed to the kernel and to tools explicitly, so nothing reads
|
|
7
10
|
* ambient state.
|
|
11
|
+
*
|
|
12
|
+
* There is one memory, not a map of them: an agent sees a slice of the single
|
|
13
|
+
* graph through its `sees` mask, which is what makes a memory shareable
|
|
14
|
+
* between agents at all.
|
|
8
15
|
*/
|
|
9
16
|
export class Services {
|
|
10
17
|
payloads;
|
|
11
|
-
|
|
18
|
+
/** the one memory graph, when the project has one */
|
|
19
|
+
memory;
|
|
20
|
+
/**
|
|
21
|
+
* Turns a path the agent can see into a host path, for the one tool that
|
|
22
|
+
* needs it: remembering a file. Supplied by whoever built the workspace,
|
|
23
|
+
* because only it knows the mounts. Without it, files cannot be
|
|
24
|
+
* remembered — which is a refusal, not a crash.
|
|
25
|
+
*/
|
|
26
|
+
resolveFile;
|
|
27
|
+
/** the driver's clock, so a tool that stamps a node stays replayable */
|
|
28
|
+
clock;
|
|
12
29
|
#skills = new Map();
|
|
13
30
|
constructor(opts = {}) {
|
|
14
31
|
const p = opts.payloads ?? new InMemoryPayloadStore();
|
|
15
32
|
this.payloads = p instanceof PayloadResolver ? p : new PayloadResolver(p);
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
33
|
+
this.memory = opts.memory;
|
|
34
|
+
this.resolveFile = opts.resolveFile;
|
|
35
|
+
this.clock = opts.clock ?? systemClock;
|
|
19
36
|
for (const s of opts.skills ?? []) {
|
|
20
37
|
this.#skills.set(s.id, s);
|
|
21
38
|
}
|
|
22
39
|
}
|
|
23
|
-
memoryStore(id) {
|
|
24
|
-
const s = this.#memory.get(id);
|
|
25
|
-
if (!s) {
|
|
26
|
-
throw new Error(`unknown memory store: ${id} (known: ${[...this.#memory.keys()]})`);
|
|
27
|
-
}
|
|
28
|
-
return s;
|
|
29
|
-
}
|
|
30
40
|
skillProvider(id) {
|
|
31
41
|
const p = this.#skills.get(id);
|
|
32
42
|
if (!p) {
|
|
@@ -34,8 +44,8 @@ export class Services {
|
|
|
34
44
|
}
|
|
35
45
|
return p;
|
|
36
46
|
}
|
|
37
|
-
hasMemory(
|
|
38
|
-
return this
|
|
47
|
+
hasMemory() {
|
|
48
|
+
return this.memory !== undefined;
|
|
39
49
|
}
|
|
40
50
|
hasSkills(id) {
|
|
41
51
|
return this.#skills.has(id);
|