kernl 0.8.3 → 0.9.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/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +21 -0
- package/dist/agent/base.d.ts +73 -0
- package/dist/agent/base.d.ts.map +1 -0
- package/dist/agent/base.js +137 -0
- package/dist/agent/index.d.ts +2 -0
- package/dist/agent/index.d.ts.map +1 -1
- package/dist/agent/index.js +2 -1
- package/dist/agent/types.d.ts +4 -0
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent.d.ts +10 -90
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +5 -171
- package/dist/api/resources/agents/agents.d.ts +11 -7
- package/dist/api/resources/agents/agents.d.ts.map +1 -1
- package/dist/api/resources/agents/agents.js +14 -8
- package/dist/kernl/__tests__/memory-config.test.d.ts +2 -0
- package/dist/kernl/__tests__/memory-config.test.d.ts.map +1 -0
- package/dist/kernl/__tests__/memory-config.test.js +157 -0
- package/dist/kernl/kernl.d.ts +11 -2
- package/dist/kernl/kernl.d.ts.map +1 -1
- package/dist/kernl/kernl.js +62 -28
- package/dist/kernl/types.d.ts +6 -5
- package/dist/kernl/types.d.ts.map +1 -1
- package/dist/lib/env.d.ts +2 -2
- package/dist/mcp/__tests__/utils.test.js +4 -2
- package/dist/mcp/utils.d.ts +1 -1
- package/dist/mcp/utils.js +1 -1
- package/dist/memory/__tests__/encoder.test.js +46 -0
- package/dist/memory/codecs/domain.js +1 -2
- package/dist/memory/encoder.d.ts +7 -7
- package/dist/memory/encoder.d.ts.map +1 -1
- package/dist/memory/encoder.js +15 -7
- package/dist/memory/memory.js +1 -1
- package/dist/memory/types.d.ts +6 -2
- package/dist/memory/types.d.ts.map +1 -1
- package/dist/realtime/agent.d.ts +17 -0
- package/dist/realtime/agent.d.ts.map +1 -0
- package/dist/realtime/agent.js +17 -0
- package/dist/realtime/channel.d.ts +30 -0
- package/dist/realtime/channel.d.ts.map +1 -0
- package/dist/realtime/channel.js +1 -0
- package/dist/realtime/index.d.ts +5 -0
- package/dist/realtime/index.d.ts.map +1 -0
- package/dist/realtime/index.js +4 -0
- package/dist/realtime/session.d.ts +98 -0
- package/dist/realtime/session.d.ts.map +1 -0
- package/dist/realtime/session.js +203 -0
- package/dist/realtime/types.d.ts +58 -0
- package/dist/realtime/types.d.ts.map +1 -0
- package/dist/realtime/types.js +1 -0
- package/dist/storage/in-memory.d.ts.map +1 -1
- package/dist/storage/in-memory.js +5 -1
- package/dist/tool/__tests__/toolkit.test.js +2 -2
- package/dist/tool/tool.d.ts +2 -1
- package/dist/tool/tool.d.ts.map +1 -1
- package/dist/tool/toolkit.d.ts +4 -4
- package/dist/tool/toolkit.d.ts.map +1 -1
- package/dist/tool/toolkit.js +2 -1
- package/dist/tool/types.d.ts +4 -4
- package/dist/tool/types.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/agent/base.ts +220 -0
- package/src/agent/index.ts +2 -0
- package/src/agent/types.ts +5 -0
- package/src/agent.ts +12 -231
- package/src/api/resources/agents/agents.ts +19 -13
- package/src/kernl/__tests__/memory-config.test.ts +203 -0
- package/src/kernl/kernl.ts +81 -39
- package/src/kernl/types.ts +6 -5
- package/src/mcp/__tests__/utils.test.ts +4 -2
- package/src/mcp/utils.ts +1 -1
- package/src/memory/__tests__/encoder.test.ts +63 -0
- package/src/memory/codecs/domain.ts +1 -1
- package/src/memory/encoder.ts +18 -10
- package/src/memory/memory.ts +1 -1
- package/src/memory/types.ts +6 -2
- package/src/realtime/agent.ts +24 -0
- package/src/realtime/channel.ts +32 -0
- package/src/realtime/index.ts +4 -0
- package/src/realtime/session.ts +259 -0
- package/src/realtime/types.ts +73 -0
- package/src/storage/in-memory.ts +9 -1
- package/src/tool/__tests__/toolkit.test.ts +2 -2
- package/src/tool/tool.ts +2 -1
- package/src/tool/toolkit.ts +6 -5
- package/src/tool/types.ts +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../../../src/api/resources/agents/agents.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../../../src/api/resources/agents/agents.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjD;;;;;;;;;;GAUG;AACH,qBAAa,OAAO;IACN,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC;IAE7D;;;;;;;OAOG;IACH,GAAG,CACD,QAAQ,GAAG,cAAc,EACzB,OAAO,SAAS,eAAe,GAAG,UAAU,EAC5C,EAAE,EAAE,MAAM,GAAG,KAAK,CAAC,QAAQ,EAAE,OAAO,CAAC,GAAG,SAAS;IAQnD;;OAEG;IACH,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAIxB;;OAEG;IACH,IAAI,IAAI,KAAK,CAAC,cAAc,EAAE,eAAe,CAAC,EAAE;IAMhD;;OAEG;IACH,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;CAGhC"}
|
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
* Thin facade over the in-process agent registry, returning live Agent instances.
|
|
5
5
|
*
|
|
6
6
|
* Note: agents are code, not persisted data; this is process-local.
|
|
7
|
+
*
|
|
8
|
+
* Currently only exposes LLM agents (kind: "llm"). RealtimeAgents are stored
|
|
9
|
+
* in the internal registry but not returned by these methods. If public access
|
|
10
|
+
* to realtime agents is needed, add a separate `kernl.realtimeAgents` resource.
|
|
7
11
|
*/
|
|
8
12
|
export class RAgents {
|
|
9
13
|
registry;
|
|
@@ -13,27 +17,29 @@ export class RAgents {
|
|
|
13
17
|
/**
|
|
14
18
|
* Get a live Agent instance by id.
|
|
15
19
|
*
|
|
20
|
+
* Only returns LLM agents. Returns undefined for realtime agents.
|
|
21
|
+
*
|
|
16
22
|
* Callers are expected to know the concrete TContext/TOutput types
|
|
17
23
|
* for their own agents and can specify them via generics.
|
|
18
24
|
*/
|
|
19
25
|
get(id) {
|
|
20
26
|
const agent = this.registry.get(id);
|
|
21
|
-
|
|
27
|
+
if (agent?.kind === "llm") {
|
|
28
|
+
return agent;
|
|
29
|
+
}
|
|
30
|
+
return undefined;
|
|
22
31
|
}
|
|
23
32
|
/**
|
|
24
|
-
* Check if an agent with the given id is registered.
|
|
33
|
+
* Check if an LLM agent with the given id is registered.
|
|
25
34
|
*/
|
|
26
35
|
has(id) {
|
|
27
|
-
return this.registry.
|
|
36
|
+
return this.registry.get(id)?.kind === "llm";
|
|
28
37
|
}
|
|
29
38
|
/**
|
|
30
|
-
* List all registered agents as live instances.
|
|
31
|
-
*
|
|
32
|
-
* Since this is a heterogeneous collection, we expose the widest safe
|
|
33
|
-
* type parameters here.
|
|
39
|
+
* List all registered LLM agents as live instances.
|
|
34
40
|
*/
|
|
35
41
|
list() {
|
|
36
|
-
return Array.from(this.registry.values());
|
|
42
|
+
return Array.from(this.registry.values()).filter((a) => a.kind === "llm");
|
|
37
43
|
}
|
|
38
44
|
/**
|
|
39
45
|
* Unregister an agent at runtime.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-config.test.d.ts","sourceRoot":"","sources":["../../../src/kernl/__tests__/memory-config.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import { Kernl } from "../kernl.js";
|
|
3
|
+
import { Agent } from "../../agent.js";
|
|
4
|
+
import { logger } from "../../lib/logger.js";
|
|
5
|
+
function createMockLanguageModel() {
|
|
6
|
+
return {
|
|
7
|
+
spec: "1.0",
|
|
8
|
+
provider: "test",
|
|
9
|
+
modelId: "test-model",
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
function createMockEmbeddingModel() {
|
|
13
|
+
return {
|
|
14
|
+
provider: "test",
|
|
15
|
+
modelId: "test-embedder",
|
|
16
|
+
embed: vi.fn(async ({ values }) => ({
|
|
17
|
+
embeddings: values.map((v) => [v.length, 0, 0]),
|
|
18
|
+
})),
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
function createMockVectorIndex() {
|
|
22
|
+
return {
|
|
23
|
+
id: "mock",
|
|
24
|
+
capabilities: () => ({
|
|
25
|
+
namespacing: false,
|
|
26
|
+
filtering: { basic: true },
|
|
27
|
+
hybrid: false,
|
|
28
|
+
}),
|
|
29
|
+
createIndex: vi.fn(),
|
|
30
|
+
deleteIndex: vi.fn(),
|
|
31
|
+
upsert: vi.fn(),
|
|
32
|
+
query: vi.fn(),
|
|
33
|
+
delete: vi.fn(),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
describe("Kernl memory config warnings", () => {
|
|
37
|
+
let warnSpy;
|
|
38
|
+
beforeEach(() => {
|
|
39
|
+
warnSpy = vi.spyOn(logger, "warn").mockImplementation(() => { });
|
|
40
|
+
});
|
|
41
|
+
afterEach(() => {
|
|
42
|
+
warnSpy.mockRestore();
|
|
43
|
+
});
|
|
44
|
+
it("warns when agent enables memory but no embedding configured", () => {
|
|
45
|
+
const kernl = new Kernl({
|
|
46
|
+
storage: {
|
|
47
|
+
vector: createMockVectorIndex(),
|
|
48
|
+
},
|
|
49
|
+
// no memory.embedding
|
|
50
|
+
});
|
|
51
|
+
const agent = new Agent({
|
|
52
|
+
id: "test-agent",
|
|
53
|
+
name: "Test Agent",
|
|
54
|
+
instructions: "test",
|
|
55
|
+
model: createMockLanguageModel(),
|
|
56
|
+
memory: { enabled: true },
|
|
57
|
+
});
|
|
58
|
+
kernl.register(agent);
|
|
59
|
+
expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining("Embeddings are not configured"));
|
|
60
|
+
});
|
|
61
|
+
it("warns when agent enables memory but no vector storage configured", () => {
|
|
62
|
+
const kernl = new Kernl({
|
|
63
|
+
memory: {
|
|
64
|
+
embedding: createMockEmbeddingModel(),
|
|
65
|
+
},
|
|
66
|
+
// no storage.vector
|
|
67
|
+
});
|
|
68
|
+
const agent = new Agent({
|
|
69
|
+
id: "test-agent",
|
|
70
|
+
name: "Test Agent",
|
|
71
|
+
instructions: "test",
|
|
72
|
+
model: createMockLanguageModel(),
|
|
73
|
+
memory: { enabled: true },
|
|
74
|
+
});
|
|
75
|
+
kernl.register(agent);
|
|
76
|
+
expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining("No vector storage configured"));
|
|
77
|
+
});
|
|
78
|
+
it("warns for both missing embedding and vector storage", () => {
|
|
79
|
+
const kernl = new Kernl({});
|
|
80
|
+
const agent = new Agent({
|
|
81
|
+
id: "test-agent",
|
|
82
|
+
name: "Test Agent",
|
|
83
|
+
instructions: "test",
|
|
84
|
+
model: createMockLanguageModel(),
|
|
85
|
+
memory: { enabled: true },
|
|
86
|
+
});
|
|
87
|
+
kernl.register(agent);
|
|
88
|
+
expect(warnSpy).toHaveBeenCalledTimes(2);
|
|
89
|
+
expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining("Embeddings are not configured"));
|
|
90
|
+
expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining("No vector storage configured"));
|
|
91
|
+
});
|
|
92
|
+
it("warns only once across multiple agents", () => {
|
|
93
|
+
const kernl = new Kernl({});
|
|
94
|
+
const agent1 = new Agent({
|
|
95
|
+
id: "agent-1",
|
|
96
|
+
name: "Agent 1",
|
|
97
|
+
instructions: "test",
|
|
98
|
+
model: createMockLanguageModel(),
|
|
99
|
+
memory: { enabled: true },
|
|
100
|
+
});
|
|
101
|
+
const agent2 = new Agent({
|
|
102
|
+
id: "agent-2",
|
|
103
|
+
name: "Agent 2",
|
|
104
|
+
instructions: "test",
|
|
105
|
+
model: createMockLanguageModel(),
|
|
106
|
+
memory: { enabled: true },
|
|
107
|
+
});
|
|
108
|
+
kernl.register(agent1);
|
|
109
|
+
kernl.register(agent2);
|
|
110
|
+
// Should only warn twice total (once for embedding, once for vector)
|
|
111
|
+
// not four times (twice per agent)
|
|
112
|
+
expect(warnSpy).toHaveBeenCalledTimes(2);
|
|
113
|
+
});
|
|
114
|
+
it("does not warn when memory config is complete", () => {
|
|
115
|
+
const kernl = new Kernl({
|
|
116
|
+
storage: {
|
|
117
|
+
vector: createMockVectorIndex(),
|
|
118
|
+
},
|
|
119
|
+
memory: {
|
|
120
|
+
embedding: createMockEmbeddingModel(),
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
const agent = new Agent({
|
|
124
|
+
id: "test-agent",
|
|
125
|
+
name: "Test Agent",
|
|
126
|
+
instructions: "test",
|
|
127
|
+
model: createMockLanguageModel(),
|
|
128
|
+
memory: { enabled: true },
|
|
129
|
+
});
|
|
130
|
+
kernl.register(agent);
|
|
131
|
+
expect(warnSpy).not.toHaveBeenCalled();
|
|
132
|
+
});
|
|
133
|
+
it("does not warn when agent does not enable memory", () => {
|
|
134
|
+
const kernl = new Kernl({});
|
|
135
|
+
const agent = new Agent({
|
|
136
|
+
id: "test-agent",
|
|
137
|
+
name: "Test Agent",
|
|
138
|
+
instructions: "test",
|
|
139
|
+
model: createMockLanguageModel(),
|
|
140
|
+
memory: { enabled: false },
|
|
141
|
+
});
|
|
142
|
+
kernl.register(agent);
|
|
143
|
+
expect(warnSpy).not.toHaveBeenCalled();
|
|
144
|
+
});
|
|
145
|
+
it("does not warn when agent has no memory config", () => {
|
|
146
|
+
const kernl = new Kernl({});
|
|
147
|
+
const agent = new Agent({
|
|
148
|
+
id: "test-agent",
|
|
149
|
+
name: "Test Agent",
|
|
150
|
+
instructions: "test",
|
|
151
|
+
model: createMockLanguageModel(),
|
|
152
|
+
// no memory config at all
|
|
153
|
+
});
|
|
154
|
+
kernl.register(agent);
|
|
155
|
+
expect(warnSpy).not.toHaveBeenCalled();
|
|
156
|
+
});
|
|
157
|
+
});
|
package/dist/kernl/kernl.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BaseAgent } from "../agent/base.js";
|
|
2
2
|
import { UnknownContext } from "../context.js";
|
|
3
3
|
import { KernlHooks } from "../lifecycle.js";
|
|
4
4
|
import type { Thread } from "../thread/index.js";
|
|
@@ -21,6 +21,9 @@ export declare class Kernl extends KernlHooks<UnknownContext, AgentOutputType> {
|
|
|
21
21
|
private readonly _models;
|
|
22
22
|
readonly storage: KernlStorage;
|
|
23
23
|
athreads: Map<string, Thread<any, any>>;
|
|
24
|
+
private readonly _memopts;
|
|
25
|
+
private readonly _storopts;
|
|
26
|
+
private warnings;
|
|
24
27
|
readonly threads: RThreads;
|
|
25
28
|
readonly agents: RAgents;
|
|
26
29
|
readonly memories: Memory;
|
|
@@ -28,7 +31,7 @@ export declare class Kernl extends KernlHooks<UnknownContext, AgentOutputType> {
|
|
|
28
31
|
/**
|
|
29
32
|
* Registers a new agent with the kernl instance.
|
|
30
33
|
*/
|
|
31
|
-
register(agent:
|
|
34
|
+
register(agent: BaseAgent): void;
|
|
32
35
|
/**
|
|
33
36
|
* Spawn a new thread - blocking execution
|
|
34
37
|
*/
|
|
@@ -51,5 +54,11 @@ export declare class Kernl extends KernlHooks<UnknownContext, AgentOutputType> {
|
|
|
51
54
|
* Schedule an existing thread - streaming execution
|
|
52
55
|
*/
|
|
53
56
|
scheduleStream<TContext, TOutput extends AgentOutputType>(thread: Thread<TContext, TOutput>): AsyncIterable<ThreadStreamEvent>;
|
|
57
|
+
/**
|
|
58
|
+
* @internal
|
|
59
|
+
*
|
|
60
|
+
* Initialize the memory system based on the storage + memory configuration.
|
|
61
|
+
*/
|
|
62
|
+
private initializeMemory;
|
|
54
63
|
}
|
|
55
64
|
//# sourceMappingURL=kernl.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kernl.d.ts","sourceRoot":"","sources":["../../src/kernl/kernl.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"kernl.d.ts","sourceRoot":"","sources":["../../src/kernl/kernl.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EAAmB,KAAK,YAAY,EAAE,MAAM,WAAW,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EACL,MAAM,EAIP,MAAM,UAAU,CAAC;AAIlB,OAAO,KAAK,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAC7E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAiC,MAAM,SAAS,CAAC;AAE3E;;;;;GAKG;AACH,qBAAa,KAAM,SAAQ,UAAU,CAAC,cAAc,EAAE,eAAe,CAAC;IACpE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqC;IAC7D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyC;IAEjE,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/B,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAa;IAEpD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA4B;IACrD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA6B;IAEvD,OAAO,CAAC,QAAQ,CAGd;IAGF,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;gBAEd,OAAO,GAAE,YAAiB;IAatC;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;IAgChC;;OAEG;IACG,KAAK,CAAC,QAAQ,EAAE,OAAO,SAAS,eAAe,EACnD,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,GAChC,OAAO,CAAC,mBAAmB,CAAC,qBAAqB,CAAC,OAAO,CAAC,CAAC,CAAC;IAS/D;;;;OAIG;IACG,QAAQ,CAAC,QAAQ,EAAE,OAAO,SAAS,eAAe,EACtD,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,GAChC,OAAO,CAAC,mBAAmB,CAAC,qBAAqB,CAAC,OAAO,CAAC,CAAC,CAAC;IAS/D;;;;OAIG;IACI,WAAW,CAAC,QAAQ,EAAE,OAAO,SAAS,eAAe,EAC1D,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,GAChC,aAAa,CAAC,iBAAiB,CAAC;IASnC;;;;OAIG;IACI,cAAc,CAAC,QAAQ,EAAE,OAAO,SAAS,eAAe,EAC7D,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,GAChC,aAAa,CAAC,iBAAiB,CAAC;IAWnC;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;CA6BzB"}
|
package/dist/kernl/kernl.js
CHANGED
|
@@ -4,6 +4,7 @@ import { InMemoryStorage } from "../storage/index.js";
|
|
|
4
4
|
import { RThreads } from "../api/resources/threads/index.js";
|
|
5
5
|
import { RAgents } from "../api/resources/agents/index.js";
|
|
6
6
|
import { Memory, MemoryByteEncoder, MemoryIndexHandle, buildMemoryIndexSchema, } from "../memory/index.js";
|
|
7
|
+
import { logger } from "../lib/logger.js";
|
|
7
8
|
/**
|
|
8
9
|
* The kernl - manages agent processes, scheduling, and task lifecycle.
|
|
9
10
|
*
|
|
@@ -15,38 +16,25 @@ export class Kernl extends KernlHooks {
|
|
|
15
16
|
_models = new Map();
|
|
16
17
|
storage;
|
|
17
18
|
athreads = new Map(); /* active threads */
|
|
19
|
+
_memopts;
|
|
20
|
+
_storopts;
|
|
21
|
+
warnings = {
|
|
22
|
+
embedding: false, // "Embeddings are not configured. If you want memories to auto-embed text content..."
|
|
23
|
+
vector: false, // "No vector storage configured. The memories.search() function will not be..."
|
|
24
|
+
}; /* tracks warnings that have been logged */
|
|
18
25
|
// --- public API ---
|
|
19
26
|
threads;
|
|
20
27
|
agents;
|
|
21
28
|
memories;
|
|
22
29
|
constructor(options = {}) {
|
|
23
30
|
super();
|
|
31
|
+
this._memopts = options.memory;
|
|
32
|
+
this._storopts = options.storage;
|
|
24
33
|
this.storage = options.storage?.db ?? new InMemoryStorage();
|
|
25
34
|
this.storage.bind({ agents: this._agents, models: this._models });
|
|
26
35
|
this.threads = new RThreads(this.storage.threads);
|
|
27
36
|
this.agents = new RAgents(this._agents);
|
|
28
|
-
|
|
29
|
-
const embeddingModel = options.memory?.embeddingModel ?? "openai/text-embedding-3-small";
|
|
30
|
-
const embedder = typeof embeddingModel === "string"
|
|
31
|
-
? resolveEmbeddingModel(embeddingModel)
|
|
32
|
-
: embeddingModel;
|
|
33
|
-
const encoder = new MemoryByteEncoder(embedder);
|
|
34
|
-
const vector = options.storage?.vector;
|
|
35
|
-
const indexId = options.memory?.indexId ?? "memories_sindex";
|
|
36
|
-
const dimensions = options.memory?.dimensions ?? 1536;
|
|
37
|
-
const providerOptions = options.memory?.indexProviderOptions ?? { schema: "kernl" };
|
|
38
|
-
this.memories = new Memory({
|
|
39
|
-
store: this.storage.memories,
|
|
40
|
-
search: vector !== undefined
|
|
41
|
-
? new MemoryIndexHandle({
|
|
42
|
-
index: vector,
|
|
43
|
-
indexId,
|
|
44
|
-
schema: buildMemoryIndexSchema({ dimensions }),
|
|
45
|
-
providerOptions,
|
|
46
|
-
})
|
|
47
|
-
: undefined,
|
|
48
|
-
encoder,
|
|
49
|
-
});
|
|
37
|
+
this.memories = this.initializeMemory();
|
|
50
38
|
}
|
|
51
39
|
/**
|
|
52
40
|
* Registers a new agent with the kernl instance.
|
|
@@ -54,12 +42,25 @@ export class Kernl extends KernlHooks {
|
|
|
54
42
|
register(agent) {
|
|
55
43
|
this._agents.set(agent.id, agent);
|
|
56
44
|
agent.bind(this);
|
|
57
|
-
//
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
45
|
+
// memory config warnings (log once)
|
|
46
|
+
if (agent.memory.enabled) {
|
|
47
|
+
if (!this._memopts?.embedding && !this.warnings.embedding) {
|
|
48
|
+
logger.warn("Embeddings are not configured. If you want memories to auto-embed text content, " +
|
|
49
|
+
"pass an embedding model into the memory config in new Kernl()");
|
|
50
|
+
this.warnings.embedding = true;
|
|
51
|
+
}
|
|
52
|
+
if (!this._storopts?.vector && !this.warnings.vector) {
|
|
53
|
+
logger.warn("No vector storage configured. The memories.search() function will not be " +
|
|
54
|
+
"available. To enable memory search, pass storage.vector in new Kernl()");
|
|
55
|
+
this.warnings.vector = true;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// auto-populate model registry for storage hydration (llm agents only - for now)
|
|
59
|
+
if (agent.kind === "llm") {
|
|
60
|
+
const key = `${agent.model.provider}/${agent.model.modelId}`;
|
|
61
|
+
if (!this._models.has(key)) {
|
|
62
|
+
this._models.set(key, agent.model);
|
|
63
|
+
}
|
|
63
64
|
}
|
|
64
65
|
}
|
|
65
66
|
/**
|
|
@@ -116,4 +117,37 @@ export class Kernl extends KernlHooks {
|
|
|
116
117
|
this.athreads.delete(thread.tid);
|
|
117
118
|
}
|
|
118
119
|
}
|
|
120
|
+
// --- private utils ---
|
|
121
|
+
/**
|
|
122
|
+
* @internal
|
|
123
|
+
*
|
|
124
|
+
* Initialize the memory system based on the storage + memory configuration.
|
|
125
|
+
*/
|
|
126
|
+
initializeMemory() {
|
|
127
|
+
const embeddingModel = this._memopts?.embedding;
|
|
128
|
+
const embedder = embeddingModel
|
|
129
|
+
? typeof embeddingModel === "string"
|
|
130
|
+
? resolveEmbeddingModel(embeddingModel)
|
|
131
|
+
: embeddingModel
|
|
132
|
+
: undefined;
|
|
133
|
+
const encoder = new MemoryByteEncoder(embedder);
|
|
134
|
+
const vector = this._storopts?.vector;
|
|
135
|
+
const indexId = this._memopts?.indexId ?? "memories_sindex";
|
|
136
|
+
const dimensions = this._memopts?.dimensions ?? 1536;
|
|
137
|
+
const providerOptions = this._memopts?.indexProviderOptions ?? {
|
|
138
|
+
schema: "kernl",
|
|
139
|
+
};
|
|
140
|
+
return new Memory({
|
|
141
|
+
store: this.storage.memories,
|
|
142
|
+
search: vector
|
|
143
|
+
? new MemoryIndexHandle({
|
|
144
|
+
index: vector,
|
|
145
|
+
indexId,
|
|
146
|
+
schema: buildMemoryIndexSchema({ dimensions }),
|
|
147
|
+
providerOptions,
|
|
148
|
+
})
|
|
149
|
+
: undefined,
|
|
150
|
+
encoder,
|
|
151
|
+
});
|
|
152
|
+
}
|
|
119
153
|
}
|
package/dist/kernl/types.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { LanguageModel, EmbeddingModel } from "@kernl-sdk/protocol";
|
|
2
2
|
import { SearchIndex } from "@kernl-sdk/retrieval";
|
|
3
|
-
import {
|
|
3
|
+
import { BaseAgent } from "../agent/base.js";
|
|
4
4
|
import { KernlStorage } from "../storage/index.js";
|
|
5
5
|
/**
|
|
6
6
|
* Storage configuration for Kernl.
|
|
@@ -27,9 +27,10 @@ export interface MemoryOptions {
|
|
|
27
27
|
* - A string like "openai/text-embedding-3-small" (resolved via provider registry)
|
|
28
28
|
* - An EmbeddingModel instance
|
|
29
29
|
*
|
|
30
|
-
*
|
|
30
|
+
* If not provided, memories will not auto-embed text content and
|
|
31
|
+
* semantic search will not be available.
|
|
31
32
|
*/
|
|
32
|
-
|
|
33
|
+
embedding?: string | EmbeddingModel<string>;
|
|
33
34
|
/**
|
|
34
35
|
* Logical index ID used by the search backend.
|
|
35
36
|
* - For pgvector: becomes the table name (with schema from indexProviderOptions)
|
|
@@ -71,10 +72,10 @@ export interface KernlOptions {
|
|
|
71
72
|
/**
|
|
72
73
|
* Agent registry interface.
|
|
73
74
|
*
|
|
74
|
-
* Satisfied by Map<string,
|
|
75
|
+
* Satisfied by Map<string, BaseAgent>.
|
|
75
76
|
*/
|
|
76
77
|
export interface AgentRegistry {
|
|
77
|
-
get(id: string):
|
|
78
|
+
get(id: string): BaseAgent<any> | undefined;
|
|
78
79
|
}
|
|
79
80
|
/**
|
|
80
81
|
* Model registry interface.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/kernl/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEnD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/kernl/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEnD,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAEzC;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,EAAE,CAAC,EAAE,YAAY,CAAC;IAElB;;;OAGG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;CAKtB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B;;;;;;;;;OASG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;IAE5C;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAE/C;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,UAAU,CAAC,EAAE,QAAQ,GAAG,WAAW,GAAG,aAAa,CAAC;CACrD;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B;;OAEG;IACH,OAAO,CAAC,EAAE,cAAc,CAAC;IAEzB;;OAEG;IACH,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB;AAED;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC;CAC7C;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,aAAa;IAC5B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAAC;CAC7C"}
|
package/dist/lib/env.d.ts
CHANGED
|
@@ -7,11 +7,11 @@ import { z } from "zod";
|
|
|
7
7
|
*/
|
|
8
8
|
declare const envSchema: z.ZodObject<{
|
|
9
9
|
LOG_LEVEL: z.ZodDefault<z.ZodEnum<{
|
|
10
|
+
error: "error";
|
|
10
11
|
trace: "trace";
|
|
11
12
|
debug: "debug";
|
|
12
13
|
info: "info";
|
|
13
14
|
warn: "warn";
|
|
14
|
-
error: "error";
|
|
15
15
|
fatal: "fatal";
|
|
16
16
|
}>>;
|
|
17
17
|
KERNL_LOG_MODEL_DATA: z.ZodPipe<z.ZodOptional<z.ZodEnum<{
|
|
@@ -31,7 +31,7 @@ declare const envSchema: z.ZodObject<{
|
|
|
31
31
|
* console.log(env.LOG_LEVEL);
|
|
32
32
|
*/
|
|
33
33
|
export declare const env: {
|
|
34
|
-
LOG_LEVEL: "
|
|
34
|
+
LOG_LEVEL: "error" | "trace" | "debug" | "info" | "warn" | "fatal";
|
|
35
35
|
KERNL_LOG_MODEL_DATA: boolean;
|
|
36
36
|
KERNL_LOG_TOOL_DATA: boolean;
|
|
37
37
|
};
|
|
@@ -52,7 +52,7 @@ describe("mcpToFunctionTool", () => {
|
|
|
52
52
|
expect(functionTool.description).toBe("Performs calculations");
|
|
53
53
|
expect(functionTool.parameters).toBeDefined();
|
|
54
54
|
});
|
|
55
|
-
it("should handle tools without inputSchema (
|
|
55
|
+
it("should handle tools without inputSchema (empty object parameters)", () => {
|
|
56
56
|
const server = createMockServer();
|
|
57
57
|
// In practice, MCP SDK tools require inputSchema, but our function handles
|
|
58
58
|
// the case where it might not be present. We use 'as any' to test this edge case.
|
|
@@ -62,7 +62,9 @@ describe("mcpToFunctionTool", () => {
|
|
|
62
62
|
};
|
|
63
63
|
const functionTool = mcpToFunctionTool(server, mcpTool);
|
|
64
64
|
expect(functionTool.id).toBe("no_params");
|
|
65
|
-
|
|
65
|
+
// When no inputSchema, we use an empty z.object({}) to match AI SDK behavior
|
|
66
|
+
expect(functionTool.parameters).toBeDefined();
|
|
67
|
+
expect(functionTool.parameters?.def.type).toBe("object");
|
|
66
68
|
});
|
|
67
69
|
it("should invoke server.callTool with correct params", async () => {
|
|
68
70
|
const server = createMockServer();
|
package/dist/mcp/utils.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import type { MCPTool, MCPToolFilter } from "./types.js";
|
|
|
5
5
|
/**
|
|
6
6
|
* Converts an MCP tool definition into a function tool usable by the SDK.
|
|
7
7
|
*/
|
|
8
|
-
export declare function mcpToFunctionTool(server: MCPServer, mcpTool: MCPTool): import("../tool/
|
|
8
|
+
export declare function mcpToFunctionTool(server: MCPServer, mcpTool: MCPTool): import("../tool/tool.js").FunctionTool<unknown, z.ZodObject<{}, z.core.$strip>, {
|
|
9
9
|
type: string;
|
|
10
10
|
text: string;
|
|
11
11
|
} | {
|
package/dist/mcp/utils.js
CHANGED
|
@@ -117,5 +117,51 @@ describe("MemoryByteEncoder", () => {
|
|
|
117
117
|
const vec = await encoder.embed("search query");
|
|
118
118
|
expect(vec).toEqual([12, 0, 0]); // "search query".length = 12
|
|
119
119
|
});
|
|
120
|
+
it("returns null when no embedder configured", async () => {
|
|
121
|
+
const encoder = new MemoryByteEncoder(); // no embedder
|
|
122
|
+
const vec = await encoder.embed("search query");
|
|
123
|
+
expect(vec).toBeNull();
|
|
124
|
+
});
|
|
125
|
+
it("throws when embedder returns empty embedding", async () => {
|
|
126
|
+
const embedder = {
|
|
127
|
+
provider: "test",
|
|
128
|
+
modelId: "test-embedder",
|
|
129
|
+
embed: vi.fn(async () => ({
|
|
130
|
+
embeddings: [[]], // empty embedding
|
|
131
|
+
})),
|
|
132
|
+
};
|
|
133
|
+
const encoder = new MemoryByteEncoder(embedder);
|
|
134
|
+
await expect(encoder.embed("test")).rejects.toThrow("Embedder returned empty embedding");
|
|
135
|
+
});
|
|
136
|
+
it("throws when embedder returns undefined embedding", async () => {
|
|
137
|
+
const embedder = {
|
|
138
|
+
provider: "test",
|
|
139
|
+
modelId: "test-embedder",
|
|
140
|
+
embed: vi.fn(async () => ({
|
|
141
|
+
embeddings: [], // no embeddings at all
|
|
142
|
+
})),
|
|
143
|
+
};
|
|
144
|
+
const encoder = new MemoryByteEncoder(embedder);
|
|
145
|
+
await expect(encoder.embed("test")).rejects.toThrow("Embedder returned empty embedding");
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
describe("without embedder", () => {
|
|
149
|
+
it("returns undefined tvec when encoding with no embedder", async () => {
|
|
150
|
+
const encoder = new MemoryByteEncoder(); // no embedder
|
|
151
|
+
const byte = { text: "Hello world" };
|
|
152
|
+
const result = await encoder.encode(byte);
|
|
153
|
+
expect(result.text).toBe("Hello world");
|
|
154
|
+
expect(result.tvec).toBeUndefined();
|
|
155
|
+
});
|
|
156
|
+
it("still produces objtext projection without embedder", async () => {
|
|
157
|
+
const encoder = new MemoryByteEncoder(); // no embedder
|
|
158
|
+
const byte = {
|
|
159
|
+
object: { preference: "coffee", shots: 2 },
|
|
160
|
+
};
|
|
161
|
+
const result = await encoder.encode(byte);
|
|
162
|
+
expect(result.text).toContain("preference: coffee");
|
|
163
|
+
expect(result.objtext).toContain("preference: coffee");
|
|
164
|
+
expect(result.tvec).toBeUndefined();
|
|
165
|
+
});
|
|
120
166
|
});
|
|
121
167
|
});
|
|
@@ -95,8 +95,7 @@ export const PATCH_CODEC = {
|
|
|
95
95
|
patch.timestamp = update.timestamp;
|
|
96
96
|
if (update.updatedAt !== undefined)
|
|
97
97
|
patch.updatedAt = update.updatedAt;
|
|
98
|
-
|
|
99
|
-
patch.metadata = update.metadata;
|
|
98
|
+
// metadata is stored in primary DB only, not indexed
|
|
100
99
|
return patch;
|
|
101
100
|
},
|
|
102
101
|
decode(_patch) {
|
package/dist/memory/encoder.d.ts
CHANGED
|
@@ -24,19 +24,17 @@ export declare const ObjectTextCodec: {
|
|
|
24
24
|
* Encoder that converts MemoryByte to IndexableByte.
|
|
25
25
|
*
|
|
26
26
|
* Extracts canonical text from content and computes embeddings.
|
|
27
|
+
* If no embedder is provided, skips embedding and tvec will be undefined.
|
|
27
28
|
*/
|
|
28
29
|
export declare class MemoryByteEncoder implements MemoryByteCodec {
|
|
29
|
-
private readonly embedder
|
|
30
|
-
constructor(embedder
|
|
30
|
+
private readonly embedder?;
|
|
31
|
+
constructor(embedder?: EmbeddingModel<string>);
|
|
31
32
|
/**
|
|
32
33
|
* Encode a MemoryByte to IndexableByte.
|
|
33
34
|
*
|
|
34
35
|
* - Produces `objtext` string projection for FTS indexing
|
|
35
36
|
* - Combines text + objtext for embedding input
|
|
36
37
|
* - Returns text (fallback to objtext if no text provided)
|
|
37
|
-
*
|
|
38
|
-
* Note: metadata is NOT set here - it comes from record.metadata
|
|
39
|
-
* via the domain codec, not from MemoryByte.object.
|
|
40
38
|
*/
|
|
41
39
|
encode(byte: MemoryByte): Promise<IndexableByte>;
|
|
42
40
|
/**
|
|
@@ -45,8 +43,10 @@ export declare class MemoryByteEncoder implements MemoryByteCodec {
|
|
|
45
43
|
decode(_indexable: IndexableByte): Promise<MemoryByte>;
|
|
46
44
|
/**
|
|
47
45
|
* Embed a text string.
|
|
48
|
-
*
|
|
46
|
+
*
|
|
47
|
+
* @returns Embedding vector, or null if no embedder configured.
|
|
48
|
+
* @throws If embedder returns empty embedding.
|
|
49
49
|
*/
|
|
50
|
-
embed(text: string): Promise<number[]>;
|
|
50
|
+
embed(text: string): Promise<number[] | null>;
|
|
51
51
|
}
|
|
52
52
|
//# sourceMappingURL=encoder.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"encoder.d.ts","sourceRoot":"","sources":["../../src/memory/encoder.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAGtE,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAQ1E;;;;;;;;GAQG;AACH,eAAO,MAAM,eAAe;IAC1B;;;;OAIG;gBACS,UAAU,GAAG,MAAM;CAOhC,CAAC;AAEF
|
|
1
|
+
{"version":3,"file":"encoder.d.ts","sourceRoot":"","sources":["../../src/memory/encoder.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAGtE,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAQ1E;;;;;;;;GAQG;AACH,eAAO,MAAM,eAAe;IAC1B;;;;OAIG;gBACS,UAAU,GAAG,MAAM;CAOhC,CAAC;AAEF;;;;;GAKG;AACH,qBAAa,iBAAkB,YAAW,eAAe;IACvD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAyB;gBAEvC,QAAQ,CAAC,EAAE,cAAc,CAAC,MAAM,CAAC;IAI7C;;;;;;OAMG;IACG,MAAM,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,aAAa,CAAC;IAyBtD;;OAEG;IACG,MAAM,CAAC,UAAU,EAAE,aAAa,GAAG,OAAO,CAAC,UAAU,CAAC;IAI5D;;;;;OAKG;IACG,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC;CAWpD"}
|