kernl 0.7.4 → 0.8.1
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 +27 -1
- package/dist/agent/types.d.ts +20 -12
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent.d.ts +7 -7
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +3 -14
- package/dist/api/resources/agents/agents.d.ts +5 -5
- package/dist/api/resources/agents/agents.d.ts.map +1 -1
- package/dist/api/resources/agents/agents.js +1 -1
- package/dist/guardrail.d.ts +19 -19
- package/dist/guardrail.d.ts.map +1 -1
- package/dist/kernl/kernl.d.ts +6 -6
- package/dist/kernl/kernl.d.ts.map +1 -1
- package/dist/lib/error.d.ts +3 -3
- package/dist/lib/error.d.ts.map +1 -1
- package/dist/lifecycle.d.ts +6 -6
- package/dist/lifecycle.d.ts.map +1 -1
- package/dist/memory/__tests__/encoder.test.d.ts +2 -0
- package/dist/memory/__tests__/encoder.test.d.ts.map +1 -0
- package/dist/memory/__tests__/encoder.test.js +121 -0
- package/dist/memory/codecs/domain.d.ts +6 -0
- package/dist/memory/codecs/domain.d.ts.map +1 -1
- package/dist/memory/codecs/domain.js +6 -0
- package/dist/memory/codecs/tpuf.d.ts.map +1 -1
- package/dist/memory/codecs/tpuf.js +2 -5
- package/dist/memory/encoder.d.ts +25 -2
- package/dist/memory/encoder.d.ts.map +1 -1
- package/dist/memory/encoder.js +46 -5
- package/dist/memory/index.d.ts +1 -1
- package/dist/memory/index.d.ts.map +1 -1
- package/dist/memory/index.js +1 -1
- package/dist/memory/schema.js +5 -4
- package/dist/memory/types.d.ts +2 -1
- package/dist/memory/types.d.ts.map +1 -1
- package/dist/thread/__tests__/integration.test.d.ts +1 -1
- package/dist/thread/__tests__/integration.test.d.ts.map +1 -1
- package/dist/thread/__tests__/integration.test.js +10 -5
- package/dist/thread/__tests__/thread.test.js +8 -8
- package/dist/thread/thread.d.ts +5 -5
- package/dist/thread/thread.d.ts.map +1 -1
- package/dist/thread/thread.js +13 -2
- package/dist/thread/types.d.ts +9 -6
- package/dist/thread/types.d.ts.map +1 -1
- package/dist/thread/utils.d.ts +7 -6
- package/dist/thread/utils.d.ts.map +1 -1
- package/dist/thread/utils.js +9 -8
- package/package.json +5 -4
- package/src/agent/types.ts +25 -29
- package/src/agent.ts +15 -28
- package/src/api/resources/agents/agents.ts +8 -8
- package/src/guardrail.ts +28 -28
- package/src/kernl/kernl.ts +12 -12
- package/src/lib/error.ts +3 -3
- package/src/lifecycle.ts +6 -6
- package/src/memory/__tests__/encoder.test.ts +154 -0
- package/src/memory/codecs/domain.ts +6 -0
- package/src/memory/codecs/tpuf.ts +2 -5
- package/src/memory/encoder.ts +51 -6
- package/src/memory/index.ts +1 -1
- package/src/memory/schema.ts +5 -5
- package/src/memory/types.ts +2 -1
- package/src/thread/__tests__/integration.test.ts +130 -146
- package/src/thread/__tests__/thread.test.ts +8 -8
- package/src/thread/thread.ts +21 -7
- package/src/thread/types.ts +9 -6
- package/src/thread/utils.ts +15 -14
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from "vitest";
|
|
2
|
+
import { MemoryByteEncoder, ObjectTextCodec } from "../encoder.js";
|
|
3
|
+
// Mock embedder that returns predictable vectors
|
|
4
|
+
function createMockEmbedder() {
|
|
5
|
+
return {
|
|
6
|
+
provider: "test",
|
|
7
|
+
modelId: "test-embedder",
|
|
8
|
+
embed: vi.fn(async ({ values }) => ({
|
|
9
|
+
embeddings: values.map((v) => [v.length, 0, 0]), // simple: [length, 0, 0]
|
|
10
|
+
})),
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
describe("ObjectTextCodec", () => {
|
|
14
|
+
it("encodes simple object to YAML", () => {
|
|
15
|
+
const obj = { name: "Tony", preference: "coffee" };
|
|
16
|
+
const result = ObjectTextCodec.encode(obj);
|
|
17
|
+
expect(result).toContain("name: Tony");
|
|
18
|
+
expect(result).toContain("preference: coffee");
|
|
19
|
+
});
|
|
20
|
+
it("sorts keys for determinism", () => {
|
|
21
|
+
const obj1 = { z: 1, a: 2, m: 3 };
|
|
22
|
+
const obj2 = { a: 2, m: 3, z: 1 };
|
|
23
|
+
expect(ObjectTextCodec.encode(obj1)).toBe(ObjectTextCodec.encode(obj2));
|
|
24
|
+
});
|
|
25
|
+
it("truncates long objects with ellipsis", () => {
|
|
26
|
+
const longValue = "x".repeat(4000);
|
|
27
|
+
const obj = { data: longValue };
|
|
28
|
+
const result = ObjectTextCodec.encode(obj);
|
|
29
|
+
expect(result.length).toBeLessThanOrEqual(3005); // 3000 + "\n..."
|
|
30
|
+
expect(result.endsWith("\n...")).toBe(true);
|
|
31
|
+
});
|
|
32
|
+
it("handles nested objects", () => {
|
|
33
|
+
const obj = {
|
|
34
|
+
user: {
|
|
35
|
+
name: "Tony",
|
|
36
|
+
prefs: { coffee: { shots: 2 } },
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
const result = ObjectTextCodec.encode(obj);
|
|
40
|
+
expect(result).toContain("user:");
|
|
41
|
+
expect(result).toContain("name: Tony");
|
|
42
|
+
expect(result).toContain("shots: 2");
|
|
43
|
+
});
|
|
44
|
+
it("handles arrays", () => {
|
|
45
|
+
const obj = { items: ["a", "b", "c"] };
|
|
46
|
+
const result = ObjectTextCodec.encode(obj);
|
|
47
|
+
expect(result).toContain("items:");
|
|
48
|
+
expect(result).toContain("- a");
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
describe("MemoryByteEncoder", () => {
|
|
52
|
+
describe("encode", () => {
|
|
53
|
+
it("encodes text-only content", async () => {
|
|
54
|
+
const embedder = createMockEmbedder();
|
|
55
|
+
const encoder = new MemoryByteEncoder(embedder);
|
|
56
|
+
const byte = { text: "Hello world" };
|
|
57
|
+
const result = await encoder.encode(byte);
|
|
58
|
+
expect(result.text).toBe("Hello world");
|
|
59
|
+
expect(result.objtext).toBeUndefined();
|
|
60
|
+
expect(result.tvec).toBeDefined();
|
|
61
|
+
expect(embedder.embed).toHaveBeenCalledWith({ values: ["Hello world"] });
|
|
62
|
+
});
|
|
63
|
+
it("encodes object-only content with projection", async () => {
|
|
64
|
+
const embedder = createMockEmbedder();
|
|
65
|
+
const encoder = new MemoryByteEncoder(embedder);
|
|
66
|
+
const byte = {
|
|
67
|
+
object: { preference: "coffee", shots: 2 },
|
|
68
|
+
};
|
|
69
|
+
const result = await encoder.encode(byte);
|
|
70
|
+
// text falls back to objtext projection
|
|
71
|
+
expect(result.text).toContain("preference: coffee");
|
|
72
|
+
expect(result.objtext).toContain("preference: coffee");
|
|
73
|
+
expect(result.tvec).toBeDefined();
|
|
74
|
+
});
|
|
75
|
+
it("combines text and object for embedding", async () => {
|
|
76
|
+
const embedder = createMockEmbedder();
|
|
77
|
+
const encoder = new MemoryByteEncoder(embedder);
|
|
78
|
+
const byte = {
|
|
79
|
+
text: "Tony likes coffee",
|
|
80
|
+
object: { shots: 2, sugar: false },
|
|
81
|
+
};
|
|
82
|
+
const result = await encoder.encode(byte);
|
|
83
|
+
expect(result.text).toBe("Tony likes coffee");
|
|
84
|
+
expect(result.objtext).toContain("shots: 2");
|
|
85
|
+
// embedding should be called with combined text
|
|
86
|
+
const embedCall = embedder.embed.mock
|
|
87
|
+
.calls[0][0];
|
|
88
|
+
expect(embedCall.values[0]).toContain("Tony likes coffee");
|
|
89
|
+
expect(embedCall.values[0]).toContain("shots: 2");
|
|
90
|
+
});
|
|
91
|
+
it("does not include metadata (lives in primary DB only)", async () => {
|
|
92
|
+
const embedder = createMockEmbedder();
|
|
93
|
+
const encoder = new MemoryByteEncoder(embedder);
|
|
94
|
+
const byte = {
|
|
95
|
+
text: "test",
|
|
96
|
+
object: { key: "value" },
|
|
97
|
+
};
|
|
98
|
+
const result = await encoder.encode(byte);
|
|
99
|
+
// metadata is not part of IndexableByte - it stays in the primary DB
|
|
100
|
+
expect("metadata" in result).toBe(false);
|
|
101
|
+
});
|
|
102
|
+
it("returns undefined tvec when no content", async () => {
|
|
103
|
+
const embedder = createMockEmbedder();
|
|
104
|
+
const encoder = new MemoryByteEncoder(embedder);
|
|
105
|
+
const byte = {};
|
|
106
|
+
const result = await encoder.encode(byte);
|
|
107
|
+
expect(result.text).toBeUndefined();
|
|
108
|
+
expect(result.objtext).toBeUndefined();
|
|
109
|
+
expect(result.tvec).toBeUndefined();
|
|
110
|
+
expect(embedder.embed).not.toHaveBeenCalled();
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
describe("embed", () => {
|
|
114
|
+
it("exposes embed method for query embedding", async () => {
|
|
115
|
+
const embedder = createMockEmbedder();
|
|
116
|
+
const encoder = new MemoryByteEncoder(embedder);
|
|
117
|
+
const vec = await encoder.embed("search query");
|
|
118
|
+
expect(vec).toEqual([12, 0, 0]); // "search query".length = 12
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
});
|
|
@@ -21,6 +21,12 @@ import type { MemoryFilter, MemoryRecord, MemoryRecordUpdate, IndexMemoryRecord,
|
|
|
21
21
|
export declare const MEMORY_FILTER: Codec<MemoryFilter, SearchFilter>;
|
|
22
22
|
/**
|
|
23
23
|
* Create a codec for MemoryRecord -> IndexMemoryRecord.
|
|
24
|
+
*
|
|
25
|
+
* Combines:
|
|
26
|
+
* - Record scope/timestamps from MemoryRecord
|
|
27
|
+
* - Indexed content (text, object projection, embeddings) from byte codec
|
|
28
|
+
*
|
|
29
|
+
* Note: metadata is NOT included - it lives in the primary DB only.
|
|
24
30
|
*/
|
|
25
31
|
export declare function recordCodec(bytecodec: MemoryByteCodec): AsyncCodec<MemoryRecord, IndexMemoryRecord>;
|
|
26
32
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"domain.d.ts","sourceRoot":"","sources":["../../../src/memory/codecs/domain.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,KAAK,EAAE,MAAM,IAAI,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEnE,OAAO,KAAK,EACV,YAAY,EACZ,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,EACjB,sBAAsB,EACtB,eAAe,EAChB,MAAM,UAAU,CAAC;AAElB;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,YAAY,EAAE,YAAY,CA0B3D,CAAC;AAEF
|
|
1
|
+
{"version":3,"file":"domain.d.ts","sourceRoot":"","sources":["../../../src/memory/codecs/domain.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,KAAK,EAAE,MAAM,IAAI,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEnE,OAAO,KAAK,EACV,YAAY,EACZ,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,EACjB,sBAAsB,EACtB,eAAe,EAChB,MAAM,UAAU,CAAC;AAElB;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,YAAY,EAAE,YAAY,CA0B3D,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CACzB,SAAS,EAAE,eAAe,GACzB,UAAU,CAAC,YAAY,EAAE,iBAAiB,CAAC,CAqB7C;AAED;;;;;;GAMG;AACH,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,kBAAkB,EAAE,sBAAsB,CAqBzE,CAAC"}
|
|
@@ -44,6 +44,12 @@ export const MEMORY_FILTER = {
|
|
|
44
44
|
};
|
|
45
45
|
/**
|
|
46
46
|
* Create a codec for MemoryRecord -> IndexMemoryRecord.
|
|
47
|
+
*
|
|
48
|
+
* Combines:
|
|
49
|
+
* - Record scope/timestamps from MemoryRecord
|
|
50
|
+
* - Indexed content (text, object projection, embeddings) from byte codec
|
|
51
|
+
*
|
|
52
|
+
* Note: metadata is NOT included - it lives in the primary DB only.
|
|
47
53
|
*/
|
|
48
54
|
export function recordCodec(bytecodec) {
|
|
49
55
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tpuf.d.ts","sourceRoot":"","sources":["../../../src/memory/codecs/tpuf.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,KAAK,EACV,WAAW,EACX,WAAW,EAEX,eAAe,EAChB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAElD;;;;GAIG;AACH,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,iBAAiB,EAAE,eAAe,
|
|
1
|
+
{"version":3,"file":"tpuf.d.ts","sourceRoot":"","sources":["../../../src/memory/codecs/tpuf.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,KAAK,EACV,WAAW,EACX,WAAW,EAEX,eAAe,EAChB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAElD;;;;GAIG;AACH,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,iBAAiB,EAAE,eAAe,CAe9D,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,WAAW,EAAE,KAAK,CAC7B,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EAC3B,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAmB5B,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,WAAW,EAAE,WAAW,CA6BtD,CAAC"}
|
|
@@ -18,11 +18,8 @@
|
|
|
18
18
|
*/
|
|
19
19
|
export const TPUF_DOC = {
|
|
20
20
|
encode(doc) {
|
|
21
|
-
const { tvec, ivec, avec, vvec,
|
|
22
|
-
const row = {
|
|
23
|
-
...rest,
|
|
24
|
-
metadata: metadata, // metadata is JSONObject | null, cast to FieldValue for UnknownDocument
|
|
25
|
-
};
|
|
21
|
+
const { tvec, ivec, avec, vvec, ...rest } = doc;
|
|
22
|
+
const row = { ...rest };
|
|
26
23
|
if (tvec)
|
|
27
24
|
row.vector = tvec;
|
|
28
25
|
return row;
|
package/dist/memory/encoder.d.ts
CHANGED
|
@@ -1,8 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* MemoryByte encoder - converts MemoryByte to IndexableByte with embeddings.
|
|
3
3
|
*/
|
|
4
|
-
import type { EmbeddingModel } from "@kernl-sdk/protocol";
|
|
4
|
+
import type { EmbeddingModel, JSONObject } from "@kernl-sdk/protocol";
|
|
5
5
|
import type { MemoryByte, IndexableByte, MemoryByteCodec } from "./types.js";
|
|
6
|
+
/**
|
|
7
|
+
* Codec for converting JSONObject to a canonical text representation.
|
|
8
|
+
*
|
|
9
|
+
* Uses YAML for human-readable, deterministic output suitable for:
|
|
10
|
+
* - Full-text search indexing
|
|
11
|
+
* - Embedding input (combined with text field)
|
|
12
|
+
*
|
|
13
|
+
* TODO: Allow users to pass custom codec via MemoryOptions.
|
|
14
|
+
*/
|
|
15
|
+
export declare const ObjectTextCodec: {
|
|
16
|
+
/**
|
|
17
|
+
* Encode a JSONObject to canonical text.
|
|
18
|
+
* Uses YAML with sorted keys for determinism.
|
|
19
|
+
* Truncates at MAX_OBJECT_TEXT_LENGTH chars.
|
|
20
|
+
*/
|
|
21
|
+
encode(obj: JSONObject): string;
|
|
22
|
+
};
|
|
6
23
|
/**
|
|
7
24
|
* Encoder that converts MemoryByte to IndexableByte.
|
|
8
25
|
*
|
|
@@ -13,7 +30,13 @@ export declare class MemoryByteEncoder implements MemoryByteCodec {
|
|
|
13
30
|
constructor(embedder: EmbeddingModel<string>);
|
|
14
31
|
/**
|
|
15
32
|
* Encode a MemoryByte to IndexableByte.
|
|
16
|
-
*
|
|
33
|
+
*
|
|
34
|
+
* - Produces `objtext` string projection for FTS indexing
|
|
35
|
+
* - Combines text + objtext for embedding input
|
|
36
|
+
* - 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.
|
|
17
40
|
*/
|
|
18
41
|
encode(byte: MemoryByte): Promise<IndexableByte>;
|
|
19
42
|
/**
|
|
@@ -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,MAAM,qBAAqB,CAAC;
|
|
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;;;;GAIG;AACH,qBAAa,iBAAkB,YAAW,eAAe;IACvD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAyB;gBAEtC,QAAQ,EAAE,cAAc,CAAC,MAAM,CAAC;IAI5C;;;;;;;;;OASG;IACG,MAAM,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,aAAa,CAAC;IAwBtD;;OAEG;IACG,MAAM,CAAC,UAAU,EAAE,aAAa,GAAG,OAAO,CAAC,UAAU,CAAC;IAI5D;;;OAGG;IACG,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;CAI7C"}
|
package/dist/memory/encoder.js
CHANGED
|
@@ -1,6 +1,34 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* MemoryByte encoder - converts MemoryByte to IndexableByte with embeddings.
|
|
3
3
|
*/
|
|
4
|
+
import { stringify as yamlStringify } from "yaml";
|
|
5
|
+
// ---------------------
|
|
6
|
+
// ObjectTextCodec
|
|
7
|
+
// ---------------------
|
|
8
|
+
const MAX_OBJECT_TEXT_LENGTH = 3000;
|
|
9
|
+
/**
|
|
10
|
+
* Codec for converting JSONObject to a canonical text representation.
|
|
11
|
+
*
|
|
12
|
+
* Uses YAML for human-readable, deterministic output suitable for:
|
|
13
|
+
* - Full-text search indexing
|
|
14
|
+
* - Embedding input (combined with text field)
|
|
15
|
+
*
|
|
16
|
+
* TODO: Allow users to pass custom codec via MemoryOptions.
|
|
17
|
+
*/
|
|
18
|
+
export const ObjectTextCodec = {
|
|
19
|
+
/**
|
|
20
|
+
* Encode a JSONObject to canonical text.
|
|
21
|
+
* Uses YAML with sorted keys for determinism.
|
|
22
|
+
* Truncates at MAX_OBJECT_TEXT_LENGTH chars.
|
|
23
|
+
*/
|
|
24
|
+
encode(obj) {
|
|
25
|
+
const yaml = yamlStringify(obj, { sortMapEntries: true });
|
|
26
|
+
if (yaml.length <= MAX_OBJECT_TEXT_LENGTH) {
|
|
27
|
+
return yaml;
|
|
28
|
+
}
|
|
29
|
+
return yaml.slice(0, MAX_OBJECT_TEXT_LENGTH) + "\n...";
|
|
30
|
+
},
|
|
31
|
+
};
|
|
4
32
|
/**
|
|
5
33
|
* Encoder that converts MemoryByte to IndexableByte.
|
|
6
34
|
*
|
|
@@ -13,19 +41,32 @@ export class MemoryByteEncoder {
|
|
|
13
41
|
}
|
|
14
42
|
/**
|
|
15
43
|
* Encode a MemoryByte to IndexableByte.
|
|
16
|
-
*
|
|
44
|
+
*
|
|
45
|
+
* - Produces `objtext` string projection for FTS indexing
|
|
46
|
+
* - Combines text + objtext for embedding input
|
|
47
|
+
* - Returns text (fallback to objtext if no text provided)
|
|
48
|
+
*
|
|
49
|
+
* Note: metadata is NOT set here - it comes from record.metadata
|
|
50
|
+
* via the domain codec, not from MemoryByte.object.
|
|
17
51
|
*/
|
|
18
52
|
async encode(byte) {
|
|
19
|
-
const
|
|
20
|
-
|
|
53
|
+
const objtext = byte.object
|
|
54
|
+
? ObjectTextCodec.encode(byte.object) // encode object as embeddable string
|
|
55
|
+
: undefined;
|
|
56
|
+
// (TODO): this behavior deserves consideration - do we always want to merge text + object?
|
|
57
|
+
//
|
|
58
|
+
// combine text + object for richer embedding
|
|
59
|
+
const combined = [byte.text, objtext].filter(Boolean).join("\n");
|
|
60
|
+
const tvec = combined ? await this.embed(combined) : undefined;
|
|
21
61
|
// TODO: embed other modalities (image, audio, video)
|
|
62
|
+
//
|
|
22
63
|
// const ivec = byte.image ? await this.embedImage(byte.image) : undefined;
|
|
23
64
|
// const avec = byte.audio ? await this.embedAudio(byte.audio) : undefined;
|
|
24
65
|
// const vvec = byte.video ? await this.embedVideo(byte.video) : undefined;
|
|
25
66
|
return {
|
|
26
|
-
text,
|
|
67
|
+
text: byte.text ?? objtext, // fallback to projection if no text
|
|
68
|
+
objtext,
|
|
27
69
|
tvec,
|
|
28
|
-
metadata: byte.object ?? null,
|
|
29
70
|
};
|
|
30
71
|
}
|
|
31
72
|
/**
|
package/dist/memory/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Memory module.
|
|
3
3
|
*/
|
|
4
4
|
export { Memory } from "./memory.js";
|
|
5
|
-
export { MemoryByteEncoder } from "./encoder.js";
|
|
5
|
+
export { MemoryByteEncoder, ObjectTextCodec } from "./encoder.js";
|
|
6
6
|
export { buildMemoryIndexSchema } from "./schema.js";
|
|
7
7
|
export { MemoryIndexHandle } from "./handle.js";
|
|
8
8
|
export type { MemoryIndexHandleConfig } from "./handle.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/memory/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/memory/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC/D,OAAO,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC7C,YAAY,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAExD,YAAY,EAEV,QAAQ,EACR,SAAS,EACT,SAAS,EACT,SAAS,EACT,UAAU,EACV,aAAa,EACb,eAAe,EAEf,WAAW,EACX,UAAU,EACV,SAAS,EACT,iBAAiB,EACjB,iBAAiB,EACjB,YAAY,EACZ,mBAAmB,EACnB,YAAY,EACZ,kBAAkB,EAClB,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EACjB,sBAAsB,EACtB,qBAAqB,EACrB,uBAAuB,GACxB,MAAM,SAAS,CAAC;AAEjB,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE3C,YAAY,EACV,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,YAAY,EACZ,aAAa,GACd,MAAM,WAAW,CAAC"}
|
package/dist/memory/index.js
CHANGED
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
* Memory module.
|
|
3
3
|
*/
|
|
4
4
|
export { Memory } from "./memory.js";
|
|
5
|
-
export { MemoryByteEncoder } from "./encoder.js";
|
|
5
|
+
export { MemoryByteEncoder, ObjectTextCodec } from "./encoder.js";
|
|
6
6
|
export { buildMemoryIndexSchema } from "./schema.js";
|
|
7
7
|
export { MemoryIndexHandle } from "./handle.js";
|
package/dist/memory/schema.js
CHANGED
|
@@ -78,6 +78,11 @@ export function buildMemoryIndexSchema(options = {}) {
|
|
|
78
78
|
fts: true,
|
|
79
79
|
optional: true,
|
|
80
80
|
},
|
|
81
|
+
objtext: {
|
|
82
|
+
type: "string",
|
|
83
|
+
fts: true,
|
|
84
|
+
optional: true,
|
|
85
|
+
},
|
|
81
86
|
// vector fields for different modalities
|
|
82
87
|
tvec: {
|
|
83
88
|
type: "vector",
|
|
@@ -103,10 +108,6 @@ export function buildMemoryIndexSchema(options = {}) {
|
|
|
103
108
|
similarity,
|
|
104
109
|
optional: true,
|
|
105
110
|
},
|
|
106
|
-
metadata: {
|
|
107
|
-
type: "object",
|
|
108
|
-
optional: true,
|
|
109
|
-
},
|
|
110
111
|
};
|
|
111
112
|
return schema;
|
|
112
113
|
}
|
package/dist/memory/types.d.ts
CHANGED
|
@@ -48,14 +48,15 @@ export interface MemoryByte {
|
|
|
48
48
|
* Search-ready projection of a MemoryByte.
|
|
49
49
|
*
|
|
50
50
|
* Contains canonical text plus embeddings for each modality.
|
|
51
|
+
* Note: metadata is NOT included - it lives in the primary DB only.
|
|
51
52
|
*/
|
|
52
53
|
export interface IndexableByte {
|
|
53
54
|
text?: string;
|
|
55
|
+
objtext?: string;
|
|
54
56
|
tvec?: number[];
|
|
55
57
|
ivec?: number[];
|
|
56
58
|
avec?: number[];
|
|
57
59
|
vvec?: number[];
|
|
58
|
-
metadata?: JSONObject | null;
|
|
59
60
|
}
|
|
60
61
|
/**
|
|
61
62
|
* Encoder that converts MemoryByte to IndexableByte with embeddings.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/memory/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAM3C,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC;AAE9B;;;;;GAKG;AACH,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,UAAU,GAAG,MAAM,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,UAAU,GAAG,MAAM,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,UAAU,GAAG,MAAM,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB;AAED
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/memory/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import "@kernl-sdk/ai/openai";
|
|
2
2
|
//# sourceMappingURL=integration.test.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"integration.test.d.ts","sourceRoot":"","sources":["../../../src/thread/__tests__/integration.test.ts"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"integration.test.d.ts","sourceRoot":"","sources":["../../../src/thread/__tests__/integration.test.ts"],"names":[],"mappings":"AAIA,OAAO,sBAAsB,CAAC"}
|
|
@@ -2,6 +2,7 @@ import { describe, it, expect, beforeAll } from "vitest";
|
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { openai } from "@ai-sdk/openai";
|
|
4
4
|
import { AISDKLanguageModel } from "@kernl-sdk/ai";
|
|
5
|
+
import "@kernl-sdk/ai/openai"; // (TMP)
|
|
5
6
|
import { Agent } from "../../agent.js";
|
|
6
7
|
import { Kernl } from "../../kernl/index.js";
|
|
7
8
|
import { tool, Toolkit } from "../../tool/index.js";
|
|
@@ -20,7 +21,7 @@ describe.skipIf(SKIP_INTEGRATION_TESTS)("Thread streaming integration", () => {
|
|
|
20
21
|
let model;
|
|
21
22
|
beforeAll(() => {
|
|
22
23
|
kernl = new Kernl();
|
|
23
|
-
model = new AISDKLanguageModel(openai("gpt-
|
|
24
|
+
model = new AISDKLanguageModel(openai("gpt-4.1"));
|
|
24
25
|
});
|
|
25
26
|
describe("stream()", () => {
|
|
26
27
|
it("should yield both delta events and complete items", async () => {
|
|
@@ -106,8 +107,12 @@ describe.skipIf(SKIP_INTEGRATION_TESTS)("Thread streaming integration", () => {
|
|
|
106
107
|
e.kind === "text-start" ||
|
|
107
108
|
e.kind === "text-end");
|
|
108
109
|
expect(streamDeltas.length).toBeGreaterThan(0);
|
|
109
|
-
// History should contain the input message
|
|
110
|
-
expect(history[0]).
|
|
110
|
+
// History should contain the input message (with ThreadEvent headers added)
|
|
111
|
+
expect(history[0]).toMatchObject({
|
|
112
|
+
kind: "message",
|
|
113
|
+
role: "user",
|
|
114
|
+
content: [{ kind: "text", text: "Count to 3" }],
|
|
115
|
+
});
|
|
111
116
|
// History should contain complete Message items
|
|
112
117
|
const historyMessages = history.filter((e) => e.kind === "message");
|
|
113
118
|
expect(historyMessages.length).toBeGreaterThan(1); // input + assistant response
|
|
@@ -279,7 +284,7 @@ describe.skipIf(SKIP_INTEGRATION_TESTS)("Thread streaming integration", () => {
|
|
|
279
284
|
expect(result.state).toBe("stopped");
|
|
280
285
|
}, 30000);
|
|
281
286
|
it("should validate structured output in blocking mode", async () => {
|
|
282
|
-
const
|
|
287
|
+
const PersonSchema = z.object({
|
|
283
288
|
name: z.string(),
|
|
284
289
|
age: z.number(),
|
|
285
290
|
});
|
|
@@ -288,7 +293,7 @@ describe.skipIf(SKIP_INTEGRATION_TESTS)("Thread streaming integration", () => {
|
|
|
288
293
|
name: "Test Structured Agent",
|
|
289
294
|
instructions: "You are a helpful assistant. Return JSON with name and age fields.",
|
|
290
295
|
model,
|
|
291
|
-
|
|
296
|
+
output: PersonSchema,
|
|
292
297
|
});
|
|
293
298
|
const input = [
|
|
294
299
|
{
|
|
@@ -937,7 +937,7 @@ describe("Thread", () => {
|
|
|
937
937
|
});
|
|
938
938
|
});
|
|
939
939
|
describe("Final Output Parsing", () => {
|
|
940
|
-
it("should return text output when
|
|
940
|
+
it("should return text output when output is 'text'", async () => {
|
|
941
941
|
const model = createMockModel(async (req) => {
|
|
942
942
|
return {
|
|
943
943
|
content: [
|
|
@@ -962,7 +962,7 @@ describe("Thread", () => {
|
|
|
962
962
|
name: "Test",
|
|
963
963
|
instructions: "Test agent",
|
|
964
964
|
model,
|
|
965
|
-
|
|
965
|
+
output: "text",
|
|
966
966
|
});
|
|
967
967
|
const kernl = new Kernl();
|
|
968
968
|
const thread = new Thread({ agent, input: userMessage("test") });
|
|
@@ -1005,7 +1005,7 @@ describe("Thread", () => {
|
|
|
1005
1005
|
name: "Test",
|
|
1006
1006
|
instructions: "Test agent",
|
|
1007
1007
|
model,
|
|
1008
|
-
|
|
1008
|
+
output: responseSchema,
|
|
1009
1009
|
});
|
|
1010
1010
|
const kernl = new Kernl();
|
|
1011
1011
|
const thread = new Thread({ agent, input: userMessage("test") });
|
|
@@ -1049,7 +1049,7 @@ describe("Thread", () => {
|
|
|
1049
1049
|
name: "Test",
|
|
1050
1050
|
instructions: "Test agent",
|
|
1051
1051
|
model,
|
|
1052
|
-
|
|
1052
|
+
output: responseSchema,
|
|
1053
1053
|
});
|
|
1054
1054
|
const kernl = new Kernl();
|
|
1055
1055
|
const thread = new Thread({ agent, input: userMessage("test") });
|
|
@@ -1089,7 +1089,7 @@ describe("Thread", () => {
|
|
|
1089
1089
|
name: "Test",
|
|
1090
1090
|
instructions: "Test agent",
|
|
1091
1091
|
model,
|
|
1092
|
-
|
|
1092
|
+
output: responseSchema,
|
|
1093
1093
|
});
|
|
1094
1094
|
const kernl = new Kernl();
|
|
1095
1095
|
const thread = new Thread({ agent, input: userMessage("test") });
|
|
@@ -1130,7 +1130,7 @@ describe("Thread", () => {
|
|
|
1130
1130
|
name: "Test",
|
|
1131
1131
|
instructions: "Test agent",
|
|
1132
1132
|
model,
|
|
1133
|
-
|
|
1133
|
+
output: responseSchema,
|
|
1134
1134
|
});
|
|
1135
1135
|
const kernl = new Kernl();
|
|
1136
1136
|
const thread = new Thread({ agent, input: userMessage("test") });
|
|
@@ -1184,7 +1184,7 @@ describe("Thread", () => {
|
|
|
1184
1184
|
name: "Test",
|
|
1185
1185
|
instructions: "Test agent",
|
|
1186
1186
|
model,
|
|
1187
|
-
|
|
1187
|
+
output: responseSchema,
|
|
1188
1188
|
});
|
|
1189
1189
|
const kernl = new Kernl();
|
|
1190
1190
|
const thread = new Thread({ agent, input: userMessage("test") });
|
|
@@ -1245,7 +1245,7 @@ describe("Thread", () => {
|
|
|
1245
1245
|
name: "Test",
|
|
1246
1246
|
instructions: "Test agent",
|
|
1247
1247
|
model,
|
|
1248
|
-
|
|
1248
|
+
output: "text",
|
|
1249
1249
|
});
|
|
1250
1250
|
const kernl = new Kernl();
|
|
1251
1251
|
const thread = new Thread({ agent, input: userMessage("test") });
|
package/dist/thread/thread.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import type { Task } from "../task.js";
|
|
|
4
4
|
import type { ResolvedAgentResponse } from "../guardrail.js";
|
|
5
5
|
import { LanguageModel } from "@kernl-sdk/protocol";
|
|
6
6
|
import type { ThreadEvent, ThreadState, ThreadOptions, ThreadEventInner, ThreadStreamEvent, ThreadExecuteResult } from "./types.js";
|
|
7
|
-
import type {
|
|
7
|
+
import type { AgentOutputType } from "../agent/types.js";
|
|
8
8
|
/**
|
|
9
9
|
* A thread drives the execution loop for an agent.
|
|
10
10
|
*
|
|
@@ -45,10 +45,10 @@ import type { AgentResponseType } from "../agent/types.js";
|
|
|
45
45
|
* If a storage implementation is present, `persist(...)` is expected to throw on failure, and
|
|
46
46
|
* that error should bubble out of `_execute()` / `stream()` and stop the thread.
|
|
47
47
|
*/
|
|
48
|
-
export declare class Thread<TContext = unknown,
|
|
48
|
+
export declare class Thread<TContext = unknown, TOutput extends AgentOutputType = "text"> {
|
|
49
49
|
readonly tid: string;
|
|
50
50
|
readonly namespace: string;
|
|
51
|
-
readonly agent: Agent<TContext,
|
|
51
|
+
readonly agent: Agent<TContext, TOutput>;
|
|
52
52
|
readonly context: Context<TContext>;
|
|
53
53
|
readonly model: LanguageModel;
|
|
54
54
|
readonly parent: Task<TContext> | null;
|
|
@@ -63,11 +63,11 @@ export declare class Thread<TContext = unknown, TResponse extends AgentResponseT
|
|
|
63
63
|
private history;
|
|
64
64
|
private abort?;
|
|
65
65
|
private storage?;
|
|
66
|
-
constructor(options: ThreadOptions<TContext,
|
|
66
|
+
constructor(options: ThreadOptions<TContext, TOutput>);
|
|
67
67
|
/**
|
|
68
68
|
* Blocking execution - runs until terminal state or interruption
|
|
69
69
|
*/
|
|
70
|
-
execute(): Promise<ThreadExecuteResult<ResolvedAgentResponse<
|
|
70
|
+
execute(): Promise<ThreadExecuteResult<ResolvedAgentResponse<TOutput>>>;
|
|
71
71
|
/**
|
|
72
72
|
* Streaming execution - returns async iterator of events
|
|
73
73
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"thread.d.ts","sourceRoot":"","sources":["../../src/thread/thread.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"thread.d.ts","sourceRoot":"","sources":["../../src/thread/thread.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AACnC,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAKzD,OAAO,EAML,aAAa,EAGd,MAAM,qBAAqB,CAAC;AAG7B,OAAO,KAAK,EAEV,WAAW,EACX,WAAW,EACX,aAAa,EACb,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EAEpB,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAWrD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,qBAAa,MAAM,CACjB,QAAQ,GAAG,OAAO,EAClB,OAAO,SAAS,eAAe,GAAG,MAAM;IAExC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACzC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;IACpC,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC;IACvC,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAIlD,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,WAAW,CAAC;IACnB,OAAO,CAAC,KAAK,CAAgB;IAC7B,OAAO,CAAC,SAAS,CAAU;IAC3B,OAAO,CAAC,OAAO,CAAwE;IAEvF,OAAO,CAAC,KAAK,CAAC,CAAkB;IAChC,OAAO,CAAC,OAAO,CAAC,CAAc;gBAElB,OAAO,EAAE,aAAa,CAAC,QAAQ,EAAE,OAAO,CAAC;IAgCrD;;OAEG;IACG,OAAO,IAAI,OAAO,CACtB,mBAAmB,CAAC,qBAAqB,CAAC,OAAO,CAAC,CAAC,CACpD;IAoBD;;OAEG;IACI,MAAM,IAAI,aAAa,CAAC,iBAAiB,CAAC;IAuBjD;;;;;OAKG;YACY,QAAQ;IAgEvB;;;;;OAKG;YACY,IAAI;IA8BnB;;;;;OAKG;YACW,UAAU;IAuCxB;;;;;;OAMG;IACH,MAAM,CAAC,GAAG,KAAK,EAAE,gBAAgB,EAAE,GAAG,WAAW,EAAE;IAiBnD;;OAEG;IACH,MAAM;IAQN;;OAEG;YACW,cAAc;IAyC5B;;;;OAIG;YACW,YAAY;IA4C1B;;OAEG;YACW,mBAAmB;CAsDlC"}
|
package/dist/thread/thread.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import assert from "assert";
|
|
2
|
+
import * as z from "zod";
|
|
2
3
|
import { Context } from "../context.js";
|
|
3
4
|
import { logger } from "../lib/logger.js";
|
|
4
5
|
import { FAILED, RUNNING, STOPPED, message, } from "@kernl-sdk/protocol";
|
|
@@ -108,7 +109,7 @@ export class Thread {
|
|
|
108
109
|
});
|
|
109
110
|
const text = getFinalResponse(items);
|
|
110
111
|
assert(text, "_execute continues until text !== null"); // (TODO): consider preventing infinite loops here
|
|
111
|
-
const parsed = parseFinalResponse(text, this.agent.
|
|
112
|
+
const parsed = parseFinalResponse(text, this.agent.output);
|
|
112
113
|
return { response: parsed, state: this.state };
|
|
113
114
|
}
|
|
114
115
|
/**
|
|
@@ -322,7 +323,7 @@ export class Thread {
|
|
|
322
323
|
if (e.kind === "tool-result" &&
|
|
323
324
|
e.state === "requires_approval" // (TODO): fix this
|
|
324
325
|
) {
|
|
325
|
-
//
|
|
326
|
+
// find the original tool call for this pending approval
|
|
326
327
|
const call = intentions.toolCalls.find((c) => c.callId === e.callId);
|
|
327
328
|
call && pendingApprovals.push(call);
|
|
328
329
|
}
|
|
@@ -403,10 +404,20 @@ export class Thread {
|
|
|
403
404
|
const all = await this.agent.tools(this.context);
|
|
404
405
|
const enabled = await filter(all, async (tool) => await tool.isEnabled(this.context, this.agent));
|
|
405
406
|
const tools = enabled.map((tool) => tool.serialize());
|
|
407
|
+
// derive responseType from agent.output
|
|
408
|
+
let responseType;
|
|
409
|
+
if (this.agent.output && this.agent.output !== "text") {
|
|
410
|
+
const schema = this.agent.output;
|
|
411
|
+
responseType = {
|
|
412
|
+
kind: "json",
|
|
413
|
+
schema: z.toJSONSchema(schema, { target: "draft-7" }),
|
|
414
|
+
};
|
|
415
|
+
}
|
|
406
416
|
return {
|
|
407
417
|
input: filtered,
|
|
408
418
|
settings,
|
|
409
419
|
tools,
|
|
420
|
+
responseType,
|
|
410
421
|
};
|
|
411
422
|
}
|
|
412
423
|
}
|