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.
@@ -1,5 +1,4 @@
1
-
2
- 
3
- > kernl@0.1.4 build /Users/andjones/Documents/projects/kernl/packages/kernl
4
- > tsc && tsc-alias
5
-
1
+
2
+ > kernl@0.2.1 build /Users/andjones/Documents/projects/kernl/packages/kernl
3
+ > tsc && tsc-alias
4
+
package/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # @kernl/core
2
2
 
3
+ ## 0.2.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Minor bug fixes and improvements
8
+ - Updated dependencies
9
+ - @kernl-sdk/protocol@0.2.1
10
+ - @kernl-sdk/shared@0.1.2
11
+
3
12
  ## 0.2.0
4
13
 
5
14
  ### Minor Changes
@@ -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;IAClC,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"}
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
@@ -10,6 +10,7 @@ export class Agent extends AgentHooks {
10
10
  model;
11
11
  modelSettings;
12
12
  toolkits;
13
+ // actions: ActionSet; /* TODO */
13
14
  guardrails;
14
15
  responseType = "text";
15
16
  resetToolChoice;
@@ -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.0",
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.0",
35
- "@kernl-sdk/shared": "^0.1.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.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()", () => {