@kernl-sdk/ai 0.3.4 → 0.4.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.
@@ -1,4 +1,4 @@
1
1
 
2
- > @kernl-sdk/ai@0.3.4 build /home/runner/work/kernl/kernl/packages/providers/ai
2
+ > @kernl-sdk/ai@0.4.0 build /home/runner/work/kernl/kernl/packages/providers/ai
3
3
  > tsc && tsc-alias --resolve-full-paths
4
4
 
package/CHANGELOG.md CHANGED
@@ -1,5 +1,58 @@
1
1
  # @kernl/ai
2
2
 
3
+ ## 0.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 8815744: **BREAKING:** Refactor event kind naming from kebab-case to dot notation
8
+
9
+ This aligns the language model stream/item kinds with the existing realtime events naming convention.
10
+
11
+ ### Kind value changes
12
+
13
+ | Old | New |
14
+ | ------------------ | ------------------ |
15
+ | `tool-call` | `tool.call` |
16
+ | `tool-result` | `tool.result` |
17
+ | `text-start` | `text.start` |
18
+ | `text-delta` | `text.delta` |
19
+ | `text-end` | `text.end` |
20
+ | `reasoning-start` | `reasoning.start` |
21
+ | `reasoning-delta` | `reasoning.delta` |
22
+ | `reasoning-end` | `reasoning.end` |
23
+ | `tool-input-start` | `tool.input.start` |
24
+ | `tool-input-delta` | `tool.input.delta` |
25
+ | `tool-input-end` | `tool.input.end` |
26
+ | `stream-start` | `stream.start` |
27
+
28
+ ### ToolInputStartEvent: `toolName` → `toolId`
29
+
30
+ The `ToolInputStartEvent` now uses `toolId` to match `ToolCall` and `ToolResult`.
31
+
32
+ ### Migration
33
+
34
+ If you have persisted thread events, run:
35
+
36
+ ```sql
37
+ UPDATE thread_events SET kind = 'tool.call' WHERE kind = 'tool-call';
38
+ UPDATE thread_events SET kind = 'tool.result' WHERE kind = 'tool-result';
39
+ ```
40
+
41
+ ### Patch Changes
42
+
43
+ - Updated dependencies [8815744]
44
+ - @kernl-sdk/protocol@0.5.0
45
+ - @kernl-sdk/retrieval@0.1.9
46
+
47
+ ## 0.3.5
48
+
49
+ ### Patch Changes
50
+
51
+ - Updated dependencies [830b52a]
52
+ - @kernl-sdk/shared@0.4.0
53
+ - @kernl-sdk/protocol@0.4.2
54
+ - @kernl-sdk/retrieval@0.1.8
55
+
3
56
  ## 0.3.4
4
57
 
5
58
  ### Patch Changes
@@ -210,7 +210,7 @@ describe.skipIf(SKIP_OPENAI_TESTS)("AISDKLanguageModel - OpenAI", () => {
210
210
  events.push(event);
211
211
  }
212
212
  // Should have text-delta events
213
- const textDeltas = events.filter((e) => e.kind === "text-delta");
213
+ const textDeltas = events.filter((e) => e.kind === "text.delta");
214
214
  expect(textDeltas.length).toBeGreaterThan(0);
215
215
  // Each text-delta should have text
216
216
  for (const delta of textDeltas) {
@@ -263,13 +263,13 @@ describe.skipIf(SKIP_OPENAI_TESTS)("AISDKLanguageModel - OpenAI", () => {
263
263
  }
264
264
  expect(events.length).toBeGreaterThan(0);
265
265
  // Should have text-delta events (for streaming UX)
266
- const textDeltas = events.filter((e) => e.kind === "text-delta");
266
+ const textDeltas = events.filter((e) => e.kind === "text.delta");
267
267
  expect(textDeltas.length).toBeGreaterThan(0);
268
268
  // Should have text-start event
269
- const textStarts = events.filter((e) => e.kind === "text-start");
269
+ const textStarts = events.filter((e) => e.kind === "text.start");
270
270
  expect(textStarts.length).toBeGreaterThan(0);
271
271
  // Should have text-end event
272
- const textEnds = events.filter((e) => e.kind === "text-end");
272
+ const textEnds = events.filter((e) => e.kind === "text.end");
273
273
  expect(textEnds.length).toBeGreaterThan(0);
274
274
  // Should have complete Message item (for history)
275
275
  const messages = events.filter((e) => e.kind === "message");
@@ -334,7 +334,7 @@ describe.skipIf(SKIP_OPENAI_TESTS)("AISDKLanguageModel - OpenAI", () => {
334
334
  }
335
335
  expect(events.length).toBeGreaterThan(0);
336
336
  // Should have a tool-call event
337
- const toolCalls = events.filter((e) => e.kind === "tool-call");
337
+ const toolCalls = events.filter((e) => e.kind === "tool.call");
338
338
  expect(toolCalls.length).toBeGreaterThan(0);
339
339
  const toolCall = toolCalls[0];
340
340
  expect(toolCall.callId).toBeDefined();
@@ -385,7 +385,7 @@ describe.skipIf(SKIP_OPENAI_TESTS)("AISDKLanguageModel - OpenAI", () => {
385
385
  });
386
386
  expect(response.content).toBeDefined();
387
387
  // Should have a tool call
388
- const toolCalls = response.content.filter((item) => item.kind === "tool-call");
388
+ const toolCalls = response.content.filter((item) => item.kind === "tool.call");
389
389
  expect(toolCalls.length).toBeGreaterThan(0);
390
390
  // Tool call should have proper structure
391
391
  const toolCall = toolCalls[0];
@@ -433,7 +433,7 @@ describe.skipIf(SKIP_OPENAI_TESTS)("AISDKLanguageModel - OpenAI", () => {
433
433
  });
434
434
  expect(response.content).toBeDefined();
435
435
  // Should have a tool call since it's required
436
- const toolCalls = response.content.filter((item) => item.kind === "tool-call");
436
+ const toolCalls = response.content.filter((item) => item.kind === "tool.call");
437
437
  expect(toolCalls.length).toBeGreaterThan(0);
438
438
  });
439
439
  it("should handle multiple tool calls", async () => {
@@ -475,7 +475,7 @@ describe.skipIf(SKIP_OPENAI_TESTS)("AISDKLanguageModel - OpenAI", () => {
475
475
  });
476
476
  expect(response.content).toBeDefined();
477
477
  // Should potentially have multiple tool calls
478
- const toolCalls = response.content.filter((item) => item.kind === "tool-call");
478
+ const toolCalls = response.content.filter((item) => item.kind === "tool.call");
479
479
  expect(toolCalls.length).toBeGreaterThan(0);
480
480
  });
481
481
  it("should handle multi-turn conversation with tool results", async () => {
@@ -513,7 +513,7 @@ describe.skipIf(SKIP_OPENAI_TESTS)("AISDKLanguageModel - OpenAI", () => {
513
513
  });
514
514
  expect(firstResponse.content).toBeDefined();
515
515
  // Extract tool calls
516
- const toolCalls = firstResponse.content.filter((item) => item.kind === "tool-call");
516
+ const toolCalls = firstResponse.content.filter((item) => item.kind === "tool.call");
517
517
  expect(toolCalls.length).toBeGreaterThan(0);
518
518
  const toolCall = toolCalls[0];
519
519
  expect(toolCall.callId).toBeDefined();
@@ -529,7 +529,7 @@ describe.skipIf(SKIP_OPENAI_TESTS)("AISDKLanguageModel - OpenAI", () => {
529
529
  },
530
530
  ...firstResponse.content,
531
531
  {
532
- kind: "tool-result",
532
+ kind: "tool.result",
533
533
  callId: toolCall.callId,
534
534
  toolId: toolCall.toolId,
535
535
  state: "completed",
@@ -612,7 +612,7 @@ describe.skipIf(SKIP_OPENAI_TESTS)("AISDKLanguageModel - OpenAI", () => {
612
612
  });
613
613
  expect(response.content).toBeDefined();
614
614
  // Should have a tool call
615
- const toolCalls = response.content.filter((item) => item.kind === "tool-call");
615
+ const toolCalls = response.content.filter((item) => item.kind === "tool.call");
616
616
  expect(toolCalls.length).toBeGreaterThan(0);
617
617
  const toolCall = toolCalls[0];
618
618
  expect(toolCall.callId).toBeDefined();
@@ -732,7 +732,7 @@ describe.skipIf(SKIP_OPENAI_TESTS)("AISDKLanguageModel - OpenAI", () => {
732
732
  }
733
733
  expect(events.length).toBeGreaterThan(0);
734
734
  // Should have text-delta events for streaming JSON
735
- const textDeltas = events.filter((e) => e.kind === "text-delta");
735
+ const textDeltas = events.filter((e) => e.kind === "text.delta");
736
736
  expect(textDeltas.length).toBeGreaterThan(0);
737
737
  // Should have a complete message with the JSON
738
738
  const messages = events.filter((e) => e.kind === "message");
@@ -803,7 +803,7 @@ describe.skipIf(SKIP_ANTHROPIC_TESTS)("AISDKLanguageModel - Anthropic", () => {
803
803
  });
804
804
  expect(response.content).toBeDefined();
805
805
  // Should have a tool call
806
- const toolCalls = response.content.filter((item) => item.kind === "tool-call");
806
+ const toolCalls = response.content.filter((item) => item.kind === "tool.call");
807
807
  expect(toolCalls.length).toBeGreaterThan(0);
808
808
  const toolCall = toolCalls[0];
809
809
  expect(toolCall.callId).toBeDefined();
@@ -861,7 +861,7 @@ describe.skipIf(SKIP_ANTHROPIC_TESTS)("AISDKLanguageModel - Anthropic", () => {
861
861
  }
862
862
  expect(events.length).toBeGreaterThan(0);
863
863
  // Should have a tool-call event
864
- const toolCalls = events.filter((e) => e.kind === "tool-call");
864
+ const toolCalls = events.filter((e) => e.kind === "tool.call");
865
865
  expect(toolCalls.length).toBeGreaterThan(0);
866
866
  const toolCall = toolCalls[0];
867
867
  expect(toolCall.callId).toBeDefined();
@@ -948,7 +948,7 @@ describe.skipIf(SKIP_ANTHROPIC_TESTS)("AISDKLanguageModel - Anthropic", () => {
948
948
  }
949
949
  expect(events.length).toBeGreaterThan(0);
950
950
  // Should have text-delta events for streaming JSON
951
- const textDeltas = events.filter((e) => e.kind === "text-delta");
951
+ const textDeltas = events.filter((e) => e.kind === "text.delta");
952
952
  expect(textDeltas.length).toBeGreaterThan(0);
953
953
  // Should have a complete message with the JSON
954
954
  const messages = events.filter((e) => e.kind === "message");
@@ -1097,7 +1097,7 @@ describe.skipIf(SKIP_GOOGLE_TESTS)("AISDKLanguageModel - Google", () => {
1097
1097
  }
1098
1098
  expect(events.length).toBeGreaterThan(0);
1099
1099
  // Should have text-delta events for streaming JSON
1100
- const textDeltas = events.filter((e) => e.kind === "text-delta");
1100
+ const textDeltas = events.filter((e) => e.kind === "text.delta");
1101
1101
  expect(textDeltas.length).toBeGreaterThan(0);
1102
1102
  // Should have a complete message with the JSON
1103
1103
  const messages = events.filter((e) => e.kind === "message");
@@ -80,19 +80,19 @@ describe("AISDKLanguageModel", () => {
80
80
  // Should have: start, 3 deltas, end, complete Message, finish
81
81
  expect(events).toHaveLength(7);
82
82
  // Check delta events
83
- expect(events[0]).toMatchObject({ kind: "text-start", id: "text-1" });
83
+ expect(events[0]).toMatchObject({ kind: "text.start", id: "text-1" });
84
84
  expect(events[1]).toMatchObject({
85
- kind: "text-delta",
85
+ kind: "text.delta",
86
86
  id: "text-1",
87
87
  text: "Hello",
88
88
  });
89
89
  expect(events[2]).toMatchObject({
90
- kind: "text-delta",
90
+ kind: "text.delta",
91
91
  id: "text-1",
92
92
  text: " ",
93
93
  });
94
94
  expect(events[3]).toMatchObject({
95
- kind: "text-delta",
95
+ kind: "text.delta",
96
96
  id: "text-1",
97
97
  text: "World",
98
98
  });
@@ -112,7 +112,7 @@ describe("AISDKLanguageModel", () => {
112
112
  });
113
113
  expect(messageEvent.id).toBeDefined();
114
114
  // Check end event (yielded after Message)
115
- expect(events[5]).toMatchObject({ kind: "text-end", id: "text-1" });
115
+ expect(events[5]).toMatchObject({ kind: "text.end", id: "text-1" });
116
116
  // Check finish event
117
117
  expect(events[6]).toMatchObject({ kind: "finish" });
118
118
  });
@@ -184,16 +184,16 @@ describe("AISDKLanguageModel", () => {
184
184
  expect(events).toHaveLength(6);
185
185
  // Check delta events
186
186
  expect(events[0]).toMatchObject({
187
- kind: "reasoning-start",
187
+ kind: "reasoning.start",
188
188
  id: "reason-1",
189
189
  });
190
190
  expect(events[1]).toMatchObject({
191
- kind: "reasoning-delta",
191
+ kind: "reasoning.delta",
192
192
  id: "reason-1",
193
193
  text: "Let me think",
194
194
  });
195
195
  expect(events[2]).toMatchObject({
196
- kind: "reasoning-delta",
196
+ kind: "reasoning.delta",
197
197
  id: "reason-1",
198
198
  text: " about this",
199
199
  });
@@ -208,7 +208,7 @@ describe("AISDKLanguageModel", () => {
208
208
  expect(reasoningEvent.id).toBeDefined();
209
209
  // Check end event (yielded after Reasoning)
210
210
  expect(events[4]).toMatchObject({
211
- kind: "reasoning-end",
211
+ kind: "reasoning.end",
212
212
  id: "reason-1",
213
213
  });
214
214
  // Check finish event
@@ -412,7 +412,7 @@ describe("AISDKLanguageModel", () => {
412
412
  // Should have tool-call and finish
413
413
  expect(events).toHaveLength(2);
414
414
  expect(events[0]).toMatchObject({
415
- kind: "tool-call",
415
+ kind: "tool.call",
416
416
  callId: "call-123",
417
417
  toolId: "calculator",
418
418
  state: IN_PROGRESS,
@@ -191,7 +191,7 @@ describe("MESSAGE codec", () => {
191
191
  describe("encode - tool-call items", () => {
192
192
  it("should encode tool-call item", () => {
193
193
  const result = MESSAGE.encode({
194
- kind: "tool-call",
194
+ kind: "tool.call",
195
195
  callId: "call-123",
196
196
  toolId: "get_weather",
197
197
  state: "completed",
@@ -203,7 +203,7 @@ describe("MESSAGE codec", () => {
203
203
  {
204
204
  type: "tool-call",
205
205
  toolCallId: "call-123",
206
- toolName: "get_weather",
206
+ toolId: "get_weather",
207
207
  input: { city: "SF" },
208
208
  providerOptions: undefined,
209
209
  },
@@ -212,7 +212,7 @@ describe("MESSAGE codec", () => {
212
212
  });
213
213
  it("should include providerMetadata for tool-call", () => {
214
214
  const result = MESSAGE.encode({
215
- kind: "tool-call",
215
+ kind: "tool.call",
216
216
  callId: "call-123",
217
217
  toolId: "get_weather",
218
218
  state: "completed",
@@ -228,7 +228,7 @@ describe("MESSAGE codec", () => {
228
228
  describe("encode - tool-result items", () => {
229
229
  it("should encode tool-result item", () => {
230
230
  const result = MESSAGE.encode({
231
- kind: "tool-result",
231
+ kind: "tool.result",
232
232
  callId: "call-123",
233
233
  toolId: "get_weather",
234
234
  state: "completed",
@@ -241,7 +241,7 @@ describe("MESSAGE codec", () => {
241
241
  {
242
242
  type: "tool-result",
243
243
  toolCallId: "call-123",
244
- toolName: "get_weather",
244
+ toolId: "get_weather",
245
245
  output: {
246
246
  type: "json",
247
247
  value: { temp: 72, conditions: "sunny" },
@@ -253,7 +253,7 @@ describe("MESSAGE codec", () => {
253
253
  });
254
254
  it("should encode tool-result item with error", () => {
255
255
  const result = MESSAGE.encode({
256
- kind: "tool-result",
256
+ kind: "tool.result",
257
257
  callId: "call-123",
258
258
  toolId: "get_weather",
259
259
  state: "failed",
@@ -266,7 +266,7 @@ describe("MESSAGE codec", () => {
266
266
  {
267
267
  type: "tool-result",
268
268
  toolCallId: "call-123",
269
- toolName: "get_weather",
269
+ toolId: "get_weather",
270
270
  output: {
271
271
  type: "error-text",
272
272
  value: "Network timeout",
@@ -80,7 +80,7 @@ describe("MODEL_SETTINGS codec", () => {
80
80
  };
81
81
  const result = MODEL_SETTINGS.encode(settings);
82
82
  expect(result).toEqual({
83
- toolChoice: { type: "tool", toolName: "get_weather" },
83
+ toolChoice: { type: "tool", toolId: "get_weather" },
84
84
  });
85
85
  });
86
86
  it("should encode providerOptions", () => {
@@ -11,7 +11,7 @@ describe("STREAM_PART codec", () => {
11
11
  };
12
12
  const result = STREAM_PART.decode(part);
13
13
  expect(result).toEqual({
14
- kind: "text-start",
14
+ kind: "text.start",
15
15
  id: "text-1",
16
16
  providerMetadata: { openai: { data: "value" } },
17
17
  });
@@ -25,7 +25,7 @@ describe("STREAM_PART codec", () => {
25
25
  };
26
26
  const result = STREAM_PART.decode(part);
27
27
  expect(result).toEqual({
28
- kind: "text-delta",
28
+ kind: "text.delta",
29
29
  id: "text-1",
30
30
  text: "Hello",
31
31
  providerMetadata: undefined,
@@ -39,7 +39,7 @@ describe("STREAM_PART codec", () => {
39
39
  };
40
40
  const result = STREAM_PART.decode(part);
41
41
  expect(result).toEqual({
42
- kind: "text-end",
42
+ kind: "text.end",
43
43
  id: "text-1",
44
44
  providerMetadata: undefined,
45
45
  });
@@ -54,7 +54,7 @@ describe("STREAM_PART codec", () => {
54
54
  };
55
55
  const result = STREAM_PART.decode(part);
56
56
  expect(result).toEqual({
57
- kind: "reasoning-start",
57
+ kind: "reasoning.start",
58
58
  id: "reason-1",
59
59
  providerMetadata: undefined,
60
60
  });
@@ -68,7 +68,7 @@ describe("STREAM_PART codec", () => {
68
68
  };
69
69
  const result = STREAM_PART.decode(part);
70
70
  expect(result).toEqual({
71
- kind: "reasoning-delta",
71
+ kind: "reasoning.delta",
72
72
  id: "reason-1",
73
73
  text: "thinking...",
74
74
  providerMetadata: undefined,
@@ -82,7 +82,7 @@ describe("STREAM_PART codec", () => {
82
82
  };
83
83
  const result = STREAM_PART.decode(part);
84
84
  expect(result).toEqual({
85
- kind: "reasoning-end",
85
+ kind: "reasoning.end",
86
86
  id: "reason-1",
87
87
  providerMetadata: undefined,
88
88
  });
@@ -99,9 +99,9 @@ describe("STREAM_PART codec", () => {
99
99
  };
100
100
  const result = STREAM_PART.decode(part);
101
101
  expect(result).toEqual({
102
- kind: "tool-input-start",
102
+ kind: "tool.input.start",
103
103
  id: "tool-1",
104
- toolName: "calculator",
104
+ toolId: "calculator",
105
105
  title: "Calculate",
106
106
  providerMetadata: undefined,
107
107
  });
@@ -115,7 +115,7 @@ describe("STREAM_PART codec", () => {
115
115
  };
116
116
  const result = STREAM_PART.decode(part);
117
117
  expect(result).toEqual({
118
- kind: "tool-input-delta",
118
+ kind: "tool.input.delta",
119
119
  id: "tool-1",
120
120
  delta: "partial input",
121
121
  providerMetadata: undefined,
@@ -129,7 +129,7 @@ describe("STREAM_PART codec", () => {
129
129
  };
130
130
  const result = STREAM_PART.decode(part);
131
131
  expect(result).toEqual({
132
- kind: "tool-input-end",
132
+ kind: "tool.input.end",
133
133
  id: "tool-1",
134
134
  providerMetadata: undefined,
135
135
  });
@@ -144,7 +144,7 @@ describe("STREAM_PART codec", () => {
144
144
  };
145
145
  const result = STREAM_PART.decode(part);
146
146
  expect(result).toEqual({
147
- kind: "tool-call",
147
+ kind: "tool.call",
148
148
  callId: "call-123",
149
149
  toolId: "get_weather",
150
150
  state: IN_PROGRESS,
@@ -162,7 +162,7 @@ describe("STREAM_PART codec", () => {
162
162
  };
163
163
  const result = STREAM_PART.decode(part);
164
164
  expect(result).toEqual({
165
- kind: "tool-call",
165
+ kind: "tool.call",
166
166
  callId: "call-empty",
167
167
  toolId: "list_issues",
168
168
  state: IN_PROGRESS,
@@ -181,7 +181,7 @@ describe("STREAM_PART codec", () => {
181
181
  };
182
182
  const result = STREAM_PART.decode(part);
183
183
  expect(result).toEqual({
184
- kind: "tool-result",
184
+ kind: "tool.result",
185
185
  callId: "call-123",
186
186
  toolId: "get_weather",
187
187
  state: "completed",
@@ -201,7 +201,7 @@ describe("STREAM_PART codec", () => {
201
201
  };
202
202
  const result = STREAM_PART.decode(part);
203
203
  expect(result).toEqual({
204
- kind: "tool-result",
204
+ kind: "tool.result",
205
205
  callId: "call-123",
206
206
  toolId: "get_weather",
207
207
  state: "failed",
@@ -224,7 +224,7 @@ describe("STREAM_PART codec", () => {
224
224
  };
225
225
  const result = STREAM_PART.decode(part);
226
226
  expect(result).toEqual({
227
- kind: "stream-start",
227
+ kind: "stream.start",
228
228
  warnings: [
229
229
  {
230
230
  type: "unsupported-setting",
@@ -359,9 +359,9 @@ describe("convertStream", () => {
359
359
  events.push(event);
360
360
  }
361
361
  expect(events).toHaveLength(4);
362
- expect(events[0]).toMatchObject({ kind: "text-start" });
363
- expect(events[1]).toMatchObject({ kind: "text-delta", text: "Hello" });
364
- expect(events[2]).toMatchObject({ kind: "text-end" });
362
+ expect(events[0]).toMatchObject({ kind: "text.start" });
363
+ expect(events[1]).toMatchObject({ kind: "text.delta", text: "Hello" });
364
+ expect(events[2]).toMatchObject({ kind: "text.end" });
365
365
  expect(events[3]).toMatchObject({ kind: "finish", finishReason: "stop" });
366
366
  });
367
367
  it("should filter out null events", async () => {
@@ -395,7 +395,7 @@ describe("convertStream", () => {
395
395
  events.push(event);
396
396
  }
397
397
  expect(events).toHaveLength(2);
398
- expect(events[0]).toMatchObject({ kind: "text-delta" });
398
+ expect(events[0]).toMatchObject({ kind: "text.delta" });
399
399
  expect(events[1]).toMatchObject({ kind: "finish" });
400
400
  });
401
401
  it("should handle empty stream", async () => {
@@ -140,7 +140,7 @@ describe("TOOL_CHOICE codec", () => {
140
140
  });
141
141
  expect(result).toEqual({
142
142
  type: "tool",
143
- toolName: "get_weather",
143
+ toolId: "get_weather",
144
144
  });
145
145
  });
146
146
  });