@kernl-sdk/ai 0.1.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.
Files changed (81) hide show
  1. package/.turbo/turbo-build.log +4 -0
  2. package/CHANGELOG.md +10 -0
  3. package/LICENSE +201 -0
  4. package/dist/__tests__/integration.test.d.ts +2 -0
  5. package/dist/__tests__/integration.test.d.ts.map +1 -0
  6. package/dist/__tests__/integration.test.js +388 -0
  7. package/dist/convert/__tests__/message.test.d.ts +2 -0
  8. package/dist/convert/__tests__/message.test.d.ts.map +1 -0
  9. package/dist/convert/__tests__/message.test.js +300 -0
  10. package/dist/convert/__tests__/response.test.d.ts +2 -0
  11. package/dist/convert/__tests__/response.test.d.ts.map +1 -0
  12. package/dist/convert/__tests__/response.test.js +49 -0
  13. package/dist/convert/__tests__/settings.test.d.ts +2 -0
  14. package/dist/convert/__tests__/settings.test.d.ts.map +1 -0
  15. package/dist/convert/__tests__/settings.test.js +144 -0
  16. package/dist/convert/__tests__/stream.test.d.ts +2 -0
  17. package/dist/convert/__tests__/stream.test.d.ts.map +1 -0
  18. package/dist/convert/__tests__/stream.test.js +389 -0
  19. package/dist/convert/__tests__/tools.test.d.ts +2 -0
  20. package/dist/convert/__tests__/tools.test.d.ts.map +1 -0
  21. package/dist/convert/__tests__/tools.test.js +152 -0
  22. package/dist/convert/message.d.ts +4 -0
  23. package/dist/convert/message.d.ts.map +1 -0
  24. package/dist/convert/message.js +122 -0
  25. package/dist/convert/messages.d.ts +4 -0
  26. package/dist/convert/messages.d.ts.map +1 -0
  27. package/dist/convert/messages.js +130 -0
  28. package/dist/convert/response.d.ts +15 -0
  29. package/dist/convert/response.d.ts.map +1 -0
  30. package/dist/convert/response.js +105 -0
  31. package/dist/convert/settings.d.ts +16 -0
  32. package/dist/convert/settings.d.ts.map +1 -0
  33. package/dist/convert/settings.js +36 -0
  34. package/dist/convert/stream.d.ts +11 -0
  35. package/dist/convert/stream.d.ts.map +1 -0
  36. package/dist/convert/stream.js +154 -0
  37. package/dist/convert/tools.d.ts +5 -0
  38. package/dist/convert/tools.d.ts.map +1 -0
  39. package/dist/convert/tools.js +42 -0
  40. package/dist/error.d.ts +8 -0
  41. package/dist/error.d.ts.map +1 -0
  42. package/dist/error.js +15 -0
  43. package/dist/index.d.ts +20 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +20 -0
  46. package/dist/language-model.d.ts +21 -0
  47. package/dist/language-model.d.ts.map +1 -0
  48. package/dist/language-model.js +60 -0
  49. package/dist/providers/anthropic.d.ts +14 -0
  50. package/dist/providers/anthropic.d.ts.map +1 -0
  51. package/dist/providers/anthropic.js +17 -0
  52. package/dist/providers/google.d.ts +14 -0
  53. package/dist/providers/google.d.ts.map +1 -0
  54. package/dist/providers/google.js +17 -0
  55. package/dist/providers/openai.d.ts +14 -0
  56. package/dist/providers/openai.d.ts.map +1 -0
  57. package/dist/providers/openai.js +17 -0
  58. package/dist/types.d.ts +1 -0
  59. package/dist/types.d.ts.map +1 -0
  60. package/dist/types.js +1 -0
  61. package/package.json +79 -0
  62. package/src/__tests__/integration.test.ts +447 -0
  63. package/src/convert/__tests__/message.test.ts +336 -0
  64. package/src/convert/__tests__/response.test.ts +63 -0
  65. package/src/convert/__tests__/settings.test.ts +188 -0
  66. package/src/convert/__tests__/stream.test.ts +460 -0
  67. package/src/convert/__tests__/tools.test.ts +179 -0
  68. package/src/convert/message.ts +150 -0
  69. package/src/convert/response.ts +144 -0
  70. package/src/convert/settings.ts +62 -0
  71. package/src/convert/stream.ts +181 -0
  72. package/src/convert/tools.ts +59 -0
  73. package/src/error.ts +16 -0
  74. package/src/index.ts +22 -0
  75. package/src/language-model.ts +77 -0
  76. package/src/providers/anthropic.ts +18 -0
  77. package/src/providers/google.ts +18 -0
  78. package/src/providers/openai.ts +18 -0
  79. package/src/types.ts +0 -0
  80. package/tsconfig.json +13 -0
  81. package/vitest.config.ts +14 -0
@@ -0,0 +1,389 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { STREAM_PART, convertStream } from "../stream";
3
+ describe("STREAM_PART codec", () => {
4
+ describe("decode - text events", () => {
5
+ it("should decode text-start event", () => {
6
+ const part = {
7
+ type: "text-start",
8
+ id: "text-1",
9
+ providerMetadata: { openai: { data: "value" } },
10
+ };
11
+ const result = STREAM_PART.decode(part);
12
+ expect(result).toEqual({
13
+ kind: "text-start",
14
+ id: "text-1",
15
+ providerMetadata: { openai: { data: "value" } },
16
+ });
17
+ });
18
+ it("should decode text-delta event", () => {
19
+ const part = {
20
+ type: "text-delta",
21
+ id: "text-1",
22
+ delta: "Hello",
23
+ providerMetadata: undefined,
24
+ };
25
+ const result = STREAM_PART.decode(part);
26
+ expect(result).toEqual({
27
+ kind: "text-delta",
28
+ id: "text-1",
29
+ text: "Hello",
30
+ providerMetadata: undefined,
31
+ });
32
+ });
33
+ it("should decode text-end event", () => {
34
+ const part = {
35
+ type: "text-end",
36
+ id: "text-1",
37
+ providerMetadata: undefined,
38
+ };
39
+ const result = STREAM_PART.decode(part);
40
+ expect(result).toEqual({
41
+ kind: "text-end",
42
+ id: "text-1",
43
+ providerMetadata: undefined,
44
+ });
45
+ });
46
+ });
47
+ describe("decode - reasoning events", () => {
48
+ it("should decode reasoning-start event", () => {
49
+ const part = {
50
+ type: "reasoning-start",
51
+ id: "reason-1",
52
+ providerMetadata: undefined,
53
+ };
54
+ const result = STREAM_PART.decode(part);
55
+ expect(result).toEqual({
56
+ kind: "reasoning-start",
57
+ id: "reason-1",
58
+ providerMetadata: undefined,
59
+ });
60
+ });
61
+ it("should decode reasoning-delta event", () => {
62
+ const part = {
63
+ type: "reasoning-delta",
64
+ id: "reason-1",
65
+ delta: "thinking...",
66
+ providerMetadata: undefined,
67
+ };
68
+ const result = STREAM_PART.decode(part);
69
+ expect(result).toEqual({
70
+ kind: "reasoning-delta",
71
+ id: "reason-1",
72
+ text: "thinking...",
73
+ providerMetadata: undefined,
74
+ });
75
+ });
76
+ it("should decode reasoning-end event", () => {
77
+ const part = {
78
+ type: "reasoning-end",
79
+ id: "reason-1",
80
+ providerMetadata: undefined,
81
+ };
82
+ const result = STREAM_PART.decode(part);
83
+ expect(result).toEqual({
84
+ kind: "reasoning-end",
85
+ id: "reason-1",
86
+ providerMetadata: undefined,
87
+ });
88
+ });
89
+ });
90
+ describe("decode - tool events", () => {
91
+ it("should decode tool-input-start event", () => {
92
+ const part = {
93
+ type: "tool-input-start",
94
+ id: "tool-1",
95
+ toolName: "calculator",
96
+ title: "Calculate",
97
+ providerMetadata: undefined,
98
+ };
99
+ const result = STREAM_PART.decode(part);
100
+ expect(result).toEqual({
101
+ kind: "tool-input-start",
102
+ id: "tool-1",
103
+ toolName: "calculator",
104
+ title: "Calculate",
105
+ providerMetadata: undefined,
106
+ });
107
+ });
108
+ it("should decode tool-input-delta event", () => {
109
+ const part = {
110
+ type: "tool-input-delta",
111
+ id: "tool-1",
112
+ delta: "partial input",
113
+ providerMetadata: undefined,
114
+ };
115
+ const result = STREAM_PART.decode(part);
116
+ expect(result).toEqual({
117
+ kind: "tool-input-delta",
118
+ id: "tool-1",
119
+ delta: "partial input",
120
+ providerMetadata: undefined,
121
+ });
122
+ });
123
+ it("should decode tool-input-end event", () => {
124
+ const part = {
125
+ type: "tool-input-end",
126
+ id: "tool-1",
127
+ providerMetadata: undefined,
128
+ };
129
+ const result = STREAM_PART.decode(part);
130
+ expect(result).toEqual({
131
+ kind: "tool-input-end",
132
+ id: "tool-1",
133
+ providerMetadata: undefined,
134
+ });
135
+ });
136
+ it("should decode tool-call event", () => {
137
+ const part = {
138
+ type: "tool-call",
139
+ toolCallId: "call-123",
140
+ toolName: "get_weather",
141
+ input: '{"city":"SF"}',
142
+ providerMetadata: undefined,
143
+ };
144
+ const result = STREAM_PART.decode(part);
145
+ expect(result).toEqual({
146
+ kind: "tool-call",
147
+ id: "call-123",
148
+ toolName: "get_weather",
149
+ arguments: '{"city":"SF"}',
150
+ providerMetadata: undefined,
151
+ });
152
+ });
153
+ it("should decode tool-result event (success)", () => {
154
+ const part = {
155
+ type: "tool-result",
156
+ toolCallId: "call-123",
157
+ toolName: "get_weather",
158
+ result: { temperature: 72 },
159
+ isError: false,
160
+ providerMetadata: undefined,
161
+ };
162
+ const result = STREAM_PART.decode(part);
163
+ expect(result).toEqual({
164
+ kind: "tool-result",
165
+ callId: "call-123",
166
+ toolId: "get_weather",
167
+ state: "completed",
168
+ result: { temperature: 72 },
169
+ error: null,
170
+ providerMetadata: undefined,
171
+ });
172
+ });
173
+ it("should decode tool-result event (error)", () => {
174
+ const part = {
175
+ type: "tool-result",
176
+ toolCallId: "call-123",
177
+ toolName: "get_weather",
178
+ result: "Network error",
179
+ isError: true,
180
+ providerMetadata: undefined,
181
+ };
182
+ const result = STREAM_PART.decode(part);
183
+ expect(result).toEqual({
184
+ kind: "tool-result",
185
+ callId: "call-123",
186
+ toolId: "get_weather",
187
+ state: "failed",
188
+ result: "Network error",
189
+ error: "Network error",
190
+ providerMetadata: undefined,
191
+ });
192
+ });
193
+ });
194
+ describe("decode - stream control events", () => {
195
+ it("should decode stream-start event", () => {
196
+ const part = {
197
+ type: "stream-start",
198
+ warnings: [
199
+ {
200
+ type: "unsupported-setting",
201
+ setting: "topK",
202
+ },
203
+ ],
204
+ };
205
+ const result = STREAM_PART.decode(part);
206
+ expect(result).toEqual({
207
+ kind: "stream-start",
208
+ warnings: [
209
+ {
210
+ type: "unsupported-setting",
211
+ setting: "topK",
212
+ details: undefined,
213
+ },
214
+ ],
215
+ });
216
+ });
217
+ it("should decode finish event", () => {
218
+ const part = {
219
+ type: "finish",
220
+ finishReason: "stop",
221
+ usage: {
222
+ inputTokens: 10,
223
+ outputTokens: 20,
224
+ totalTokens: 30,
225
+ },
226
+ providerMetadata: undefined,
227
+ };
228
+ const result = STREAM_PART.decode(part);
229
+ expect(result).toEqual({
230
+ kind: "finish",
231
+ finishReason: "stop",
232
+ usage: {
233
+ inputTokens: 10,
234
+ outputTokens: 20,
235
+ totalTokens: 30,
236
+ reasoningTokens: undefined,
237
+ cachedInputTokens: undefined,
238
+ },
239
+ providerMetadata: undefined,
240
+ });
241
+ });
242
+ it("should decode error event", () => {
243
+ const part = {
244
+ type: "error",
245
+ error: "Connection failed",
246
+ };
247
+ const result = STREAM_PART.decode(part);
248
+ expect(result).toEqual({
249
+ kind: "error",
250
+ error: "Connection failed",
251
+ });
252
+ });
253
+ it("should decode raw event", () => {
254
+ const part = {
255
+ type: "raw",
256
+ rawValue: { custom: "data" },
257
+ };
258
+ const result = STREAM_PART.decode(part);
259
+ expect(result).toEqual({
260
+ kind: "raw",
261
+ rawValue: { custom: "data" },
262
+ });
263
+ });
264
+ it("should return null for response-metadata", () => {
265
+ const part = {
266
+ type: "response-metadata",
267
+ };
268
+ const result = STREAM_PART.decode(part);
269
+ expect(result).toBeNull();
270
+ });
271
+ });
272
+ describe("decode - file and source events", () => {
273
+ it("should decode file event as raw", () => {
274
+ const part = {
275
+ type: "file",
276
+ id: "file-1",
277
+ filename: "test.txt",
278
+ mediaType: "text/plain",
279
+ data: "base64data",
280
+ };
281
+ const result = STREAM_PART.decode(part);
282
+ expect(result).toEqual({
283
+ kind: "raw",
284
+ rawValue: part,
285
+ });
286
+ });
287
+ it("should decode source event as raw", () => {
288
+ const part = {
289
+ type: "source",
290
+ sourceType: "url",
291
+ id: "source-1",
292
+ url: "https://example.com",
293
+ };
294
+ const result = STREAM_PART.decode(part);
295
+ expect(result).toEqual({
296
+ kind: "raw",
297
+ rawValue: part,
298
+ });
299
+ });
300
+ });
301
+ describe("encode", () => {
302
+ it("should throw unimplemented error", () => {
303
+ expect(() => STREAM_PART.encode(null)).toThrow("codec:unimplemented");
304
+ });
305
+ });
306
+ });
307
+ describe("convertStream", () => {
308
+ it("should convert stream to async iterable", async () => {
309
+ const parts = [
310
+ { type: "text-start", id: "text-1", providerMetadata: undefined },
311
+ {
312
+ type: "text-delta",
313
+ id: "text-1",
314
+ delta: "Hello",
315
+ providerMetadata: undefined,
316
+ },
317
+ { type: "text-end", id: "text-1", providerMetadata: undefined },
318
+ {
319
+ type: "finish",
320
+ finishReason: "stop",
321
+ usage: { inputTokens: 5, outputTokens: 10, totalTokens: 15 },
322
+ providerMetadata: undefined,
323
+ },
324
+ ];
325
+ const stream = new ReadableStream({
326
+ start(controller) {
327
+ for (const part of parts) {
328
+ controller.enqueue(part);
329
+ }
330
+ controller.close();
331
+ },
332
+ });
333
+ const events = [];
334
+ for await (const event of convertStream(stream)) {
335
+ events.push(event);
336
+ }
337
+ expect(events).toHaveLength(4);
338
+ expect(events[0]).toMatchObject({ kind: "text-start" });
339
+ expect(events[1]).toMatchObject({ kind: "text-delta", text: "Hello" });
340
+ expect(events[2]).toMatchObject({ kind: "text-end" });
341
+ expect(events[3]).toMatchObject({ kind: "finish", finishReason: "stop" });
342
+ });
343
+ it("should filter out null events", async () => {
344
+ const parts = [
345
+ {
346
+ type: "text-delta",
347
+ id: "text-1",
348
+ delta: "Hello",
349
+ providerMetadata: undefined,
350
+ },
351
+ {
352
+ type: "response-metadata",
353
+ }, // This should be filtered out
354
+ {
355
+ type: "finish",
356
+ finishReason: "stop",
357
+ usage: { inputTokens: 5, outputTokens: 10, totalTokens: 15 },
358
+ providerMetadata: undefined,
359
+ },
360
+ ];
361
+ const stream = new ReadableStream({
362
+ start(controller) {
363
+ for (const part of parts) {
364
+ controller.enqueue(part);
365
+ }
366
+ controller.close();
367
+ },
368
+ });
369
+ const events = [];
370
+ for await (const event of convertStream(stream)) {
371
+ events.push(event);
372
+ }
373
+ expect(events).toHaveLength(2);
374
+ expect(events[0]).toMatchObject({ kind: "text-delta" });
375
+ expect(events[1]).toMatchObject({ kind: "finish" });
376
+ });
377
+ it("should handle empty stream", async () => {
378
+ const stream = new ReadableStream({
379
+ start(controller) {
380
+ controller.close();
381
+ },
382
+ });
383
+ const events = [];
384
+ for await (const event of convertStream(stream)) {
385
+ events.push(event);
386
+ }
387
+ expect(events).toHaveLength(0);
388
+ });
389
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=tools.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.test.d.ts","sourceRoot":"","sources":["../../../src/convert/__tests__/tools.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,152 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { TOOL, TOOL_CHOICE } from "../tools";
3
+ describe("TOOL codec", () => {
4
+ describe("encode - function tools", () => {
5
+ it("should encode function tool with basic schema", () => {
6
+ const result = TOOL.encode({
7
+ kind: "function",
8
+ name: "get_weather",
9
+ description: "Get current weather for a location",
10
+ parameters: {
11
+ type: "object",
12
+ properties: {
13
+ city: { type: "string" },
14
+ },
15
+ required: ["city"],
16
+ },
17
+ });
18
+ expect(result).toEqual({
19
+ type: "function",
20
+ name: "get_weather",
21
+ description: "Get current weather for a location",
22
+ inputSchema: {
23
+ type: "object",
24
+ properties: {
25
+ city: { type: "string" },
26
+ },
27
+ required: ["city"],
28
+ },
29
+ providerOptions: undefined,
30
+ });
31
+ });
32
+ it("should encode function tool without description", () => {
33
+ const result = TOOL.encode({
34
+ kind: "function",
35
+ name: "simple_tool",
36
+ parameters: {
37
+ type: "object",
38
+ properties: {},
39
+ },
40
+ });
41
+ expect(result).toEqual({
42
+ type: "function",
43
+ name: "simple_tool",
44
+ description: undefined,
45
+ inputSchema: {
46
+ type: "object",
47
+ properties: {},
48
+ },
49
+ providerOptions: undefined,
50
+ });
51
+ });
52
+ it("should encode function tool with complex schema", () => {
53
+ const result = TOOL.encode({
54
+ kind: "function",
55
+ name: "search",
56
+ description: "Search for information",
57
+ parameters: {
58
+ type: "object",
59
+ properties: {
60
+ query: {
61
+ type: "string",
62
+ description: "Search query",
63
+ },
64
+ filters: {
65
+ type: "object",
66
+ properties: {
67
+ category: { type: "string" },
68
+ maxResults: { type: "number" },
69
+ },
70
+ },
71
+ },
72
+ required: ["query"],
73
+ },
74
+ });
75
+ expect(result.type).toBe("function");
76
+ expect(result.name).toBe("search");
77
+ if (result.type === "function" && result.inputSchema.properties) {
78
+ expect(result.inputSchema.properties.query).toEqual({
79
+ type: "string",
80
+ description: "Search query",
81
+ });
82
+ expect(result.inputSchema.required).toEqual(["query"]);
83
+ }
84
+ });
85
+ });
86
+ describe("encode - provider-defined tools", () => {
87
+ it("should encode provider-defined tool", () => {
88
+ const result = TOOL.encode({
89
+ kind: "provider-defined",
90
+ id: "mcp.tool-123",
91
+ name: "custom_mcp_tool",
92
+ args: { param1: "value1" },
93
+ });
94
+ expect(result).toEqual({
95
+ type: "provider-defined",
96
+ id: "mcp.tool-123",
97
+ name: "custom_mcp_tool",
98
+ args: { param1: "value1" },
99
+ });
100
+ });
101
+ it("should encode provider-defined tool without args", () => {
102
+ const result = TOOL.encode({
103
+ kind: "provider-defined",
104
+ id: "mcp.tool-id",
105
+ name: "tool_name",
106
+ args: {},
107
+ });
108
+ expect(result).toEqual({
109
+ type: "provider-defined",
110
+ id: "mcp.tool-id",
111
+ name: "tool_name",
112
+ args: {},
113
+ });
114
+ });
115
+ });
116
+ describe("decode", () => {
117
+ it("should throw unimplemented error", () => {
118
+ expect(() => TOOL.decode({})).toThrow("codec:unimplemented");
119
+ });
120
+ });
121
+ });
122
+ describe("TOOL_CHOICE codec", () => {
123
+ describe("encode", () => {
124
+ it("should encode 'auto' tool choice", () => {
125
+ const result = TOOL_CHOICE.encode({ kind: "auto" });
126
+ expect(result).toEqual({ type: "auto" });
127
+ });
128
+ it("should encode 'none' tool choice", () => {
129
+ const result = TOOL_CHOICE.encode({ kind: "none" });
130
+ expect(result).toEqual({ type: "none" });
131
+ });
132
+ it("should encode 'required' tool choice", () => {
133
+ const result = TOOL_CHOICE.encode({ kind: "required" });
134
+ expect(result).toEqual({ type: "required" });
135
+ });
136
+ it("should encode specific tool choice", () => {
137
+ const result = TOOL_CHOICE.encode({
138
+ kind: "tool",
139
+ toolId: "get_weather",
140
+ });
141
+ expect(result).toEqual({
142
+ type: "tool",
143
+ toolName: "get_weather",
144
+ });
145
+ });
146
+ });
147
+ describe("decode", () => {
148
+ it("should throw unimplemented error", () => {
149
+ expect(() => TOOL_CHOICE.decode({})).toThrow("codec:unimplemented");
150
+ });
151
+ });
152
+ });
@@ -0,0 +1,4 @@
1
+ import type { Codec, LanguageModelItem } from "@kernl-sdk/protocol";
2
+ import type { LanguageModelV3Message } from "@ai-sdk/provider";
3
+ export declare const MESSAGE: Codec<LanguageModelItem, LanguageModelV3Message>;
4
+ //# sourceMappingURL=message.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message.d.ts","sourceRoot":"","sources":["../../src/convert/message.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,KAAK,EACV,sBAAsB,EAKvB,MAAM,kBAAkB,CAAC;AAE1B,eAAO,MAAM,OAAO,EAAE,KAAK,CAAC,iBAAiB,EAAE,sBAAsB,CA4IpE,CAAC"}
@@ -0,0 +1,122 @@
1
+ export const MESSAGE = {
2
+ encode: (item) => {
3
+ switch (item.kind) {
4
+ case "message": {
5
+ switch (item.role) {
6
+ case "system": {
7
+ const content = item.content
8
+ .filter((part) => part.kind === "text")
9
+ .map((part) => (part.kind === "text" ? part.text : ""))
10
+ .join("\n");
11
+ return {
12
+ role: "system",
13
+ content: content,
14
+ providerOptions: item.providerMetadata,
15
+ };
16
+ }
17
+ case "user": {
18
+ const content = [];
19
+ for (const part of item.content) {
20
+ if (part.kind === "text") {
21
+ content.push({
22
+ type: "text",
23
+ text: part.text,
24
+ providerOptions: part.providerMetadata,
25
+ });
26
+ }
27
+ else if (part.kind === "file") {
28
+ content.push({
29
+ type: "file",
30
+ filename: part.filename,
31
+ data: part.data,
32
+ mediaType: part.mimeType,
33
+ providerOptions: part.providerMetadata,
34
+ });
35
+ }
36
+ }
37
+ return {
38
+ role: "user",
39
+ content,
40
+ providerOptions: item.providerMetadata,
41
+ };
42
+ }
43
+ case "assistant": {
44
+ const content = [];
45
+ for (const part of item.content) {
46
+ if (part.kind === "text") {
47
+ content.push({
48
+ type: "text",
49
+ text: part.text,
50
+ providerOptions: part.providerMetadata,
51
+ });
52
+ }
53
+ else if (part.kind === "file") {
54
+ content.push({
55
+ type: "file",
56
+ filename: part.filename,
57
+ data: part.data,
58
+ mediaType: part.mimeType,
59
+ providerOptions: part.providerMetadata,
60
+ });
61
+ }
62
+ }
63
+ return {
64
+ role: "assistant",
65
+ content,
66
+ providerOptions: item.providerMetadata,
67
+ };
68
+ }
69
+ }
70
+ break;
71
+ }
72
+ case "reasoning": {
73
+ return {
74
+ role: "assistant",
75
+ content: [
76
+ {
77
+ type: "reasoning",
78
+ text: "text" in item ? item.text : "",
79
+ providerOptions: item.providerMetadata,
80
+ },
81
+ ],
82
+ };
83
+ }
84
+ case "tool-call": {
85
+ return {
86
+ role: "assistant",
87
+ content: [
88
+ {
89
+ type: "tool-call",
90
+ toolCallId: item.callId,
91
+ toolName: item.toolId,
92
+ input: JSON.parse(item.arguments),
93
+ providerOptions: item.providerMetadata,
94
+ },
95
+ ],
96
+ };
97
+ }
98
+ case "tool-result": {
99
+ return {
100
+ role: "tool",
101
+ content: [
102
+ {
103
+ type: "tool-result",
104
+ toolCallId: item.callId,
105
+ toolName: item.toolId,
106
+ output: {
107
+ type: "json",
108
+ value: item.result,
109
+ },
110
+ providerOptions: item.providerMetadata,
111
+ },
112
+ ],
113
+ };
114
+ }
115
+ default:
116
+ throw new Error(`Unsupported LanguageModelItem kind: ${item.kind}`);
117
+ }
118
+ },
119
+ decode: () => {
120
+ throw new Error("codec:unimplemented");
121
+ },
122
+ };
@@ -0,0 +1,4 @@
1
+ import type { Codec, LanguageModelItem } from "@kernl-sdk/protocol";
2
+ import type { LanguageModelV3Message } from "ai";
3
+ export declare const messages: Codec<LanguageModelItem[], LanguageModelV3Message[]>;
4
+ //# sourceMappingURL=messages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/convert/messages.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,KAAK,EACV,sBAAsB,EAMvB,MAAM,IAAI,CAAC;AAEZ,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,iBAAiB,EAAE,EAAE,sBAAsB,EAAE,CAwIzE,CAAC"}