kernl 0.2.0 → 0.2.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
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
>
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
|
|
2
|
+
> kernl@0.2.1 build /Users/andjones/Documents/projects/kernl/packages/kernl
|
|
3
|
+
> tsc && tsc-alias
|
|
4
|
+
|
package/CHANGELOG.md
CHANGED
package/dist/agent.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,4BAA4B,EAE7B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAK9B,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACpE,OAAO,KAAK,EACV,YAAY,EACZ,aAAa,EACb,mBAAmB,EACnB,iBAAiB,EAClB,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAEzD,qBAAa,KAAK,CACd,QAAQ,GAAG,cAAc,EACzB,SAAS,SAAS,iBAAiB,GAAG,YAAY,CAEpD,SAAQ,UAAU,CAAC,QAAQ,EAAE,SAAS,CACtC,YAAW,WAAW,CAAC,QAAQ,EAAE,SAAS,CAAC;IAE3C,OAAO,CAAC,KAAK,CAAC,CAAQ;IAEtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;IAEvE,KAAK,EAAE,aAAa,CAAC;IACrB,aAAa,EAAE,4BAA4B,CAAC;IAC5C,QAAQ,EAAE,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,4BAA4B,EAE7B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAK9B,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACpE,OAAO,KAAK,EACV,YAAY,EACZ,aAAa,EACb,mBAAmB,EACnB,iBAAiB,EAClB,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAEzD,qBAAa,KAAK,CACd,QAAQ,GAAG,cAAc,EACzB,SAAS,SAAS,iBAAiB,GAAG,YAAY,CAEpD,SAAQ,UAAU,CAAC,QAAQ,EAAE,SAAS,CACtC,YAAW,WAAW,CAAC,QAAQ,EAAE,SAAS,CAAC;IAE3C,OAAO,CAAC,KAAK,CAAC,CAAQ;IAEtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;IAEvE,KAAK,EAAE,aAAa,CAAC;IACrB,aAAa,EAAE,4BAA4B,CAAC;IAC5C,QAAQ,EAAE,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC;IAGlC,UAAU,EAAE;QACV,KAAK,EAAE,cAAc,EAAE,CAAC;QACxB,MAAM,EAAE,eAAe,CAAC,iBAAiB,CAAC,EAAE,CAAC;KAC9C,CAAC;IACF,YAAY,EAAE,SAAS,CAAuB;IAC9C,eAAe,EAAE,OAAO,CAAC;gBAgBb,MAAM,EAAE,WAAW,CAAC,QAAQ,EAAE,SAAS,CAAC;IA0CpD;;OAEG;IACH,IAAI,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAIxB;;OAEG;IACG,GAAG,CACP,YAAY,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,aAAa,CAAC,QAAQ,CAAC,GAChC,OAAO,CAAC,mBAAmB,CAAC,qBAAqB,CAAC,SAAS,CAAC,CAAC,CAAC;IAqBjE;;;;OAIG;IACI,MAAM,CACX,YAAY,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,aAAa,CAAC,QAAQ,CAAC,GAChC,aAAa,CAAC,iBAAiB,CAAC;IAsBnC;;;;;OAKG;IACH,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,SAAS;IAQ5C;;;;;;;;;;OAUG;IACG,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;CAoBnE"}
|
package/dist/agent.js
CHANGED
|
@@ -184,6 +184,74 @@ describe.skipIf(SKIP_INTEGRATION_TESTS)("Thread streaming integration", () => {
|
|
|
184
184
|
expect(textContent).toBeDefined();
|
|
185
185
|
expect(textContent.text).toContain("42");
|
|
186
186
|
}, 30000);
|
|
187
|
+
it("should properly encode tool results with matching callIds for multi-turn", async () => {
|
|
188
|
+
const multiplyTool = tool({
|
|
189
|
+
id: "multiply",
|
|
190
|
+
name: "multiply",
|
|
191
|
+
description: "Multiply two numbers",
|
|
192
|
+
parameters: z.object({
|
|
193
|
+
a: z.number().describe("First number"),
|
|
194
|
+
b: z.number().describe("Second number"),
|
|
195
|
+
}),
|
|
196
|
+
execute: async (ctx, { a, b }) => {
|
|
197
|
+
return a * b;
|
|
198
|
+
},
|
|
199
|
+
});
|
|
200
|
+
const toolkit = new Toolkit({
|
|
201
|
+
id: "math",
|
|
202
|
+
tools: [multiplyTool],
|
|
203
|
+
});
|
|
204
|
+
const agent = new Agent({
|
|
205
|
+
id: "test-multi-turn",
|
|
206
|
+
name: "Test Multi-Turn Agent",
|
|
207
|
+
instructions: "You are a helpful assistant that can do math.",
|
|
208
|
+
model,
|
|
209
|
+
toolkits: [toolkit],
|
|
210
|
+
});
|
|
211
|
+
const input = [
|
|
212
|
+
{
|
|
213
|
+
kind: "message",
|
|
214
|
+
id: "msg-1",
|
|
215
|
+
role: "user",
|
|
216
|
+
content: [{ kind: "text", text: "What is 7 times 6?" }],
|
|
217
|
+
},
|
|
218
|
+
];
|
|
219
|
+
const thread = new Thread(kernl, agent, input);
|
|
220
|
+
const events = [];
|
|
221
|
+
// Collect all events from the stream
|
|
222
|
+
for await (const event of thread.stream()) {
|
|
223
|
+
events.push(event);
|
|
224
|
+
}
|
|
225
|
+
// Find the tool call and result
|
|
226
|
+
const toolCalls = events.filter((e) => e.kind === "tool-call");
|
|
227
|
+
const toolResults = events.filter((e) => e.kind === "tool-result");
|
|
228
|
+
expect(toolCalls.length).toBeGreaterThan(0);
|
|
229
|
+
expect(toolResults.length).toBeGreaterThan(0);
|
|
230
|
+
const multiplyCall = toolCalls[0];
|
|
231
|
+
const multiplyResult = toolResults[0];
|
|
232
|
+
// Verify callId matches between tool call and result
|
|
233
|
+
expect(multiplyCall.callId).toBe(multiplyResult.callId);
|
|
234
|
+
expect(multiplyCall.toolId).toBe("multiply");
|
|
235
|
+
expect(multiplyResult.toolId).toBe("multiply");
|
|
236
|
+
// Verify the tool result has the correct structure
|
|
237
|
+
expect(multiplyResult.callId).toBeDefined();
|
|
238
|
+
expect(typeof multiplyResult.callId).toBe("string");
|
|
239
|
+
expect(multiplyResult.callId.length).toBeGreaterThan(0);
|
|
240
|
+
// Verify history contains both with matching callIds
|
|
241
|
+
const history = thread.history;
|
|
242
|
+
const historyToolCall = history.find((e) => e.kind === "tool-call" && e.toolId === "multiply");
|
|
243
|
+
const historyToolResult = history.find((e) => e.kind === "tool-result" && e.toolId === "multiply");
|
|
244
|
+
expect(historyToolCall).toBeDefined();
|
|
245
|
+
expect(historyToolResult).toBeDefined();
|
|
246
|
+
expect(historyToolCall.callId).toBe(historyToolResult.callId);
|
|
247
|
+
// Verify final response uses the tool result
|
|
248
|
+
const messages = events.filter((e) => e.kind === "message");
|
|
249
|
+
const assistantMessage = messages.find((m) => m.role === "assistant");
|
|
250
|
+
expect(assistantMessage).toBeDefined();
|
|
251
|
+
const textContent = assistantMessage.content.find((c) => c.kind === "text");
|
|
252
|
+
expect(textContent).toBeDefined();
|
|
253
|
+
expect(textContent.text).toContain("42");
|
|
254
|
+
}, 30000);
|
|
187
255
|
});
|
|
188
256
|
describe("execute()", () => {
|
|
189
257
|
it("should consume stream and return final response", async () => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kernl",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "A modern AI agent framework",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"kernl",
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
"@modelcontextprotocol/sdk": "^1.20.2",
|
|
32
32
|
"pino": "^9.6.0",
|
|
33
33
|
"zod": "^4.1.12",
|
|
34
|
-
"@kernl-sdk/protocol": "0.2.
|
|
35
|
-
"@kernl-sdk/shared": "^0.1.
|
|
34
|
+
"@kernl-sdk/protocol": "0.2.1",
|
|
35
|
+
"@kernl-sdk/shared": "^0.1.2"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@ai-sdk/openai": "3.0.0-beta.57",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"tsc-alias": "^1.8.10",
|
|
41
41
|
"typescript": "5.9.2",
|
|
42
42
|
"vitest": "^4.0.8",
|
|
43
|
-
"@kernl-sdk/ai": "0.1.
|
|
43
|
+
"@kernl-sdk/ai": "0.1.2"
|
|
44
44
|
},
|
|
45
45
|
"scripts": {
|
|
46
46
|
"build": "tsc && tsc-alias",
|
package/src/agent.ts
CHANGED
|
@@ -39,6 +39,8 @@ export class Agent<
|
|
|
39
39
|
model: LanguageModel;
|
|
40
40
|
modelSettings: LanguageModelRequestSettings;
|
|
41
41
|
toolkits: BaseToolkit<TContext>[];
|
|
42
|
+
// actions: ActionSet; /* TODO */
|
|
43
|
+
|
|
42
44
|
guardrails: {
|
|
43
45
|
input: InputGuardrail[];
|
|
44
46
|
output: OutputGuardrail<AgentResponseType>[];
|
|
@@ -266,6 +266,106 @@ describe.skipIf(SKIP_INTEGRATION_TESTS)(
|
|
|
266
266
|
},
|
|
267
267
|
30000,
|
|
268
268
|
);
|
|
269
|
+
|
|
270
|
+
it(
|
|
271
|
+
"should properly encode tool results with matching callIds for multi-turn",
|
|
272
|
+
async () => {
|
|
273
|
+
const multiplyTool = tool({
|
|
274
|
+
id: "multiply",
|
|
275
|
+
name: "multiply",
|
|
276
|
+
description: "Multiply two numbers",
|
|
277
|
+
parameters: z.object({
|
|
278
|
+
a: z.number().describe("First number"),
|
|
279
|
+
b: z.number().describe("Second number"),
|
|
280
|
+
}),
|
|
281
|
+
execute: async (ctx, { a, b }) => {
|
|
282
|
+
return a * b;
|
|
283
|
+
},
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
const toolkit = new Toolkit({
|
|
287
|
+
id: "math",
|
|
288
|
+
tools: [multiplyTool],
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
const agent = new Agent({
|
|
292
|
+
id: "test-multi-turn",
|
|
293
|
+
name: "Test Multi-Turn Agent",
|
|
294
|
+
instructions: "You are a helpful assistant that can do math.",
|
|
295
|
+
model,
|
|
296
|
+
toolkits: [toolkit],
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
const input: ThreadEvent[] = [
|
|
300
|
+
{
|
|
301
|
+
kind: "message",
|
|
302
|
+
id: "msg-1",
|
|
303
|
+
role: "user",
|
|
304
|
+
content: [{ kind: "text", text: "What is 7 times 6?" }],
|
|
305
|
+
},
|
|
306
|
+
];
|
|
307
|
+
|
|
308
|
+
const thread = new Thread(kernl, agent, input);
|
|
309
|
+
const events: ThreadStreamEvent[] = [];
|
|
310
|
+
|
|
311
|
+
// Collect all events from the stream
|
|
312
|
+
for await (const event of thread.stream()) {
|
|
313
|
+
events.push(event);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// Find the tool call and result
|
|
317
|
+
const toolCalls = events.filter(
|
|
318
|
+
(e): e is Extract<ThreadStreamEvent, { kind: "tool-call" }> =>
|
|
319
|
+
e.kind === "tool-call",
|
|
320
|
+
);
|
|
321
|
+
const toolResults = events.filter(
|
|
322
|
+
(e): e is Extract<ThreadStreamEvent, { kind: "tool-result" }> =>
|
|
323
|
+
e.kind === "tool-result",
|
|
324
|
+
);
|
|
325
|
+
|
|
326
|
+
expect(toolCalls.length).toBeGreaterThan(0);
|
|
327
|
+
expect(toolResults.length).toBeGreaterThan(0);
|
|
328
|
+
|
|
329
|
+
const multiplyCall = toolCalls[0];
|
|
330
|
+
const multiplyResult = toolResults[0];
|
|
331
|
+
|
|
332
|
+
// Verify callId matches between tool call and result
|
|
333
|
+
expect(multiplyCall.callId).toBe(multiplyResult.callId);
|
|
334
|
+
expect(multiplyCall.toolId).toBe("multiply");
|
|
335
|
+
expect(multiplyResult.toolId).toBe("multiply");
|
|
336
|
+
|
|
337
|
+
// Verify the tool result has the correct structure
|
|
338
|
+
expect(multiplyResult.callId).toBeDefined();
|
|
339
|
+
expect(typeof multiplyResult.callId).toBe("string");
|
|
340
|
+
expect(multiplyResult.callId.length).toBeGreaterThan(0);
|
|
341
|
+
|
|
342
|
+
// Verify history contains both with matching callIds
|
|
343
|
+
const history = (thread as any).history as ThreadEvent[];
|
|
344
|
+
const historyToolCall = history.find(
|
|
345
|
+
(e) => e.kind === "tool-call" && e.toolId === "multiply",
|
|
346
|
+
);
|
|
347
|
+
const historyToolResult = history.find(
|
|
348
|
+
(e) => e.kind === "tool-result" && e.toolId === "multiply",
|
|
349
|
+
);
|
|
350
|
+
|
|
351
|
+
expect(historyToolCall).toBeDefined();
|
|
352
|
+
expect(historyToolResult).toBeDefined();
|
|
353
|
+
expect((historyToolCall as any).callId).toBe(
|
|
354
|
+
(historyToolResult as any).callId,
|
|
355
|
+
);
|
|
356
|
+
|
|
357
|
+
// Verify final response uses the tool result
|
|
358
|
+
const messages = events.filter((e) => e.kind === "message");
|
|
359
|
+
const assistantMessage = messages.find((m: any) => m.role === "assistant");
|
|
360
|
+
expect(assistantMessage).toBeDefined();
|
|
361
|
+
const textContent = (assistantMessage as any).content.find(
|
|
362
|
+
(c: any) => c.kind === "text",
|
|
363
|
+
);
|
|
364
|
+
expect(textContent).toBeDefined();
|
|
365
|
+
expect(textContent.text).toContain("42");
|
|
366
|
+
},
|
|
367
|
+
30000,
|
|
368
|
+
);
|
|
269
369
|
});
|
|
270
370
|
|
|
271
371
|
describe("execute()", () => {
|