smoltalk 0.0.52 → 0.0.53

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 (48) hide show
  1. package/dist/classes/ToolCall.d.ts +8 -6
  2. package/dist/classes/ToolCall.js +9 -1
  3. package/dist/classes/message/AssistantMessage.d.ts +37 -13
  4. package/dist/classes/message/AssistantMessage.js +27 -19
  5. package/dist/classes/message/BaseMessage.d.ts +1 -0
  6. package/dist/classes/message/BaseMessage.js +5 -0
  7. package/dist/classes/message/DeveloperMessage.d.ts +12 -6
  8. package/dist/classes/message/DeveloperMessage.js +13 -6
  9. package/dist/classes/message/SystemMessage.d.ts +12 -6
  10. package/dist/classes/message/SystemMessage.js +13 -6
  11. package/dist/classes/message/ToolMessage.d.ts +13 -7
  12. package/dist/classes/message/ToolMessage.js +15 -7
  13. package/dist/classes/message/UserMessage.d.ts +9 -6
  14. package/dist/classes/message/UserMessage.js +11 -3
  15. package/dist/classes/message/index.js +1 -1
  16. package/dist/client.d.ts +4 -7
  17. package/dist/client.js +10 -7
  18. package/dist/clients/baseClient.d.ts +4 -5
  19. package/dist/clients/baseClient.js +26 -26
  20. package/dist/clients/google.js +2 -1
  21. package/dist/clients/ollama.js +78 -72
  22. package/dist/clients/openai.js +5 -3
  23. package/dist/clients/openaiResponses.js +2 -3
  24. package/dist/functions.d.ts +6 -2
  25. package/dist/functions.js +11 -32
  26. package/dist/model.d.ts +14 -12
  27. package/dist/model.js +36 -12
  28. package/dist/models.d.ts +13 -1
  29. package/dist/models.js +12 -0
  30. package/dist/statelogClient.d.ts +3 -4
  31. package/dist/statelogClient.js +6 -4
  32. package/dist/strategies/baseStrategy.js +2 -2
  33. package/dist/strategies/fallbackStrategy.d.ts +6 -7
  34. package/dist/strategies/fallbackStrategy.js +61 -48
  35. package/dist/strategies/idStrategy.d.ts +5 -3
  36. package/dist/strategies/idStrategy.js +44 -10
  37. package/dist/strategies/index.d.ts +3 -3
  38. package/dist/strategies/index.js +20 -22
  39. package/dist/strategies/raceStrategy.d.ts +3 -2
  40. package/dist/strategies/raceStrategy.js +8 -1
  41. package/dist/strategies/types.d.ts +68 -13
  42. package/dist/strategies/types.js +57 -1
  43. package/dist/types.d.ts +32 -11
  44. package/dist/types.js +32 -0
  45. package/dist/util/tool.js +4 -0
  46. package/dist/util.d.ts +10 -0
  47. package/dist/util.js +34 -0
  48. package/package.json +4 -5
@@ -1,10 +1,12 @@
1
+ import { z } from "zod";
1
2
  import { FunctionCall } from "@google/genai";
2
3
  import { ResponseInputItem } from "openai/resources/responses/responses.js";
3
- export type ToolCallJSON = {
4
- id: string;
5
- name: string;
6
- arguments: Record<string, any>;
7
- };
4
+ export declare const ToolCallJSONSchema: z.ZodObject<{
5
+ id: z.ZodDefault<z.ZodString>;
6
+ name: z.ZodString;
7
+ arguments: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodAny>>;
8
+ }, z.core.$strip>;
9
+ export type ToolCallJSON = z.infer<typeof ToolCallJSONSchema>;
8
10
  export type ToolCallOptions = {};
9
11
  export declare class ToolCall {
10
12
  private _id;
@@ -16,7 +18,7 @@ export declare class ToolCall {
16
18
  get name(): string;
17
19
  get arguments(): Record<string, any>;
18
20
  toJSON(): ToolCallJSON;
19
- static fromJSON(json: any): ToolCall;
21
+ static fromJSON(json: unknown): ToolCall;
20
22
  toOpenAI(): any;
21
23
  toGoogle(): {
22
24
  functionCall: FunctionCall;
@@ -1,4 +1,10 @@
1
+ import { z } from "zod";
1
2
  import { getLogger } from "../logger.js";
3
+ export const ToolCallJSONSchema = z.object({
4
+ id: z.string().default(""),
5
+ name: z.string(),
6
+ arguments: z.record(z.string(), z.any()).default({}),
7
+ });
2
8
  export class ToolCall {
3
9
  _id;
4
10
  _name;
@@ -14,6 +20,7 @@ export class ToolCall {
14
20
  }
15
21
  catch (e) {
16
22
  this.logger.error(`Failed to parse arguments for ToolCall ${name} with id ${id}:`, e, args);
23
+ this.logger.debug("Falling back to empty arguments object for ToolCall", { name, id, rawArgs: args });
17
24
  this._arguments = {};
18
25
  }
19
26
  }
@@ -38,7 +45,8 @@ export class ToolCall {
38
45
  };
39
46
  }
40
47
  static fromJSON(json) {
41
- return new ToolCall(json.id, json.name, json.arguments);
48
+ const parsed = ToolCallJSONSchema.parse(json);
49
+ return new ToolCall(parsed.id, parsed.name, parsed.arguments);
42
50
  }
43
51
  toOpenAI() {
44
52
  return {
@@ -1,21 +1,45 @@
1
+ import { z } from "zod";
1
2
  import { BaseMessage, MessageClass } from "./BaseMessage.js";
2
3
  import { CostEstimate, TextPart, ThinkingBlock, TokenUsage } from "../../types.js";
3
4
  import { ChatCompletionMessageParam } from "openai/resources";
4
5
  import { Content } from "@google/genai";
5
- import { ToolCall, ToolCallJSON } from "../ToolCall.js";
6
+ import { ToolCall } from "../ToolCall.js";
6
7
  import { Message } from "ollama";
7
8
  import type { ResponseInputItem } from "openai/resources/responses/responses.js";
8
- export type AssistantMessageJSON = {
9
- role: "assistant";
10
- content: string | Array<TextPart> | null;
11
- name: string | undefined;
12
- audio: any | null | undefined;
13
- refusal: string | null | undefined;
14
- toolCalls: ToolCallJSON[] | undefined;
15
- thinkingBlocks: ThinkingBlock[] | undefined;
16
- usage: TokenUsage | undefined;
17
- cost: CostEstimate | undefined;
18
- };
9
+ export declare const AssistantMessageJSONSchema: z.ZodObject<{
10
+ role: z.ZodLiteral<"assistant">;
11
+ content: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodObject<{
12
+ type: z.ZodLiteral<"text">;
13
+ text: z.ZodString;
14
+ }, z.core.$strip>>, z.ZodNull]>;
15
+ name: z.ZodOptional<z.ZodString>;
16
+ audio: z.ZodOptional<z.ZodAny>;
17
+ refusal: z.ZodOptional<z.ZodNullable<z.ZodString>>;
18
+ toolCalls: z.ZodOptional<z.ZodArray<z.ZodObject<{
19
+ id: z.ZodDefault<z.ZodString>;
20
+ name: z.ZodString;
21
+ arguments: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodAny>>;
22
+ }, z.core.$strip>>>;
23
+ thinkingBlocks: z.ZodOptional<z.ZodArray<z.ZodObject<{
24
+ text: z.ZodString;
25
+ signature: z.ZodString;
26
+ }, z.core.$strip>>>;
27
+ rawData: z.ZodOptional<z.ZodAny>;
28
+ usage: z.ZodOptional<z.ZodObject<{
29
+ inputTokens: z.ZodNumber;
30
+ outputTokens: z.ZodNumber;
31
+ cachedInputTokens: z.ZodOptional<z.ZodNumber>;
32
+ totalTokens: z.ZodOptional<z.ZodNumber>;
33
+ }, z.core.$strip>>;
34
+ cost: z.ZodOptional<z.ZodObject<{
35
+ inputCost: z.ZodNumber;
36
+ outputCost: z.ZodNumber;
37
+ cachedInputCost: z.ZodOptional<z.ZodNumber>;
38
+ totalCost: z.ZodNumber;
39
+ currency: z.ZodString;
40
+ }, z.core.$strip>>;
41
+ }, z.core.$strip>;
42
+ export type AssistantMessageJSON = z.infer<typeof AssistantMessageJSONSchema>;
19
43
  export declare class AssistantMessage extends BaseMessage implements MessageClass {
20
44
  _role: "assistant";
21
45
  _content: string | Array<TextPart> | null;
@@ -49,7 +73,7 @@ export declare class AssistantMessage extends BaseMessage implements MessageClas
49
73
  get usage(): TokenUsage | undefined;
50
74
  get cost(): CostEstimate | undefined;
51
75
  toJSON(): AssistantMessageJSON;
52
- static fromJSON(json: any): AssistantMessage;
76
+ static fromJSON(json: unknown): AssistantMessage;
53
77
  toOpenAIMessage(): ChatCompletionMessageParam;
54
78
  toOpenAIResponseInputItem(): ResponseInputItem | ResponseInputItem[];
55
79
  toGoogleMessage(): Content;
@@ -1,5 +1,19 @@
1
+ import { z } from "zod";
1
2
  import { BaseMessage } from "./BaseMessage.js";
2
- import { ToolCall } from "../ToolCall.js";
3
+ import { CostEstimateSchema, TextPartSchema, ThinkingBlockSchema, TokenUsageSchema, } from "../../types.js";
4
+ import { ToolCall, ToolCallJSONSchema } from "../ToolCall.js";
5
+ export const AssistantMessageJSONSchema = z.object({
6
+ role: z.literal("assistant"),
7
+ content: z.union([z.string(), z.array(TextPartSchema), z.null()]),
8
+ name: z.string().optional(),
9
+ audio: z.any().optional(),
10
+ refusal: z.string().nullable().optional(),
11
+ toolCalls: z.array(ToolCallJSONSchema).optional(),
12
+ thinkingBlocks: z.array(ThinkingBlockSchema).optional(),
13
+ rawData: z.any().optional(),
14
+ usage: TokenUsageSchema.optional(),
15
+ cost: CostEstimateSchema.optional(),
16
+ });
3
17
  export class AssistantMessage extends BaseMessage {
4
18
  _role = "assistant";
5
19
  _content;
@@ -24,12 +38,7 @@ export class AssistantMessage extends BaseMessage {
24
38
  this._cost = options.cost;
25
39
  }
26
40
  get content() {
27
- if (this._content === null || this._content === undefined) {
28
- return "";
29
- }
30
- return typeof this._content === "string"
31
- ? this._content
32
- : JSON.stringify(this._content);
41
+ return this.contentToString(this._content);
33
42
  }
34
43
  set content(value) {
35
44
  this._content = value;
@@ -75,17 +84,16 @@ export class AssistantMessage extends BaseMessage {
75
84
  };
76
85
  }
77
86
  static fromJSON(json) {
78
- return new AssistantMessage(json.content, {
79
- name: json.name,
80
- audio: json.audio,
81
- refusal: json.refusal,
82
- toolCalls: json.toolCalls
83
- ? json.toolCalls.map((tcJson) => ToolCall.fromJSON(tcJson))
84
- : undefined,
85
- thinkingBlocks: json.thinkingBlocks,
86
- rawData: json.rawData,
87
- usage: json.usage,
88
- cost: json.cost,
87
+ const parsed = AssistantMessageJSONSchema.parse(json);
88
+ return new AssistantMessage(parsed.content, {
89
+ name: parsed.name,
90
+ audio: parsed.audio,
91
+ refusal: parsed.refusal,
92
+ toolCalls: parsed.toolCalls?.map((tc) => ToolCall.fromJSON(tc)),
93
+ thinkingBlocks: parsed.thinkingBlocks,
94
+ rawData: parsed.rawData,
95
+ usage: parsed.usage,
96
+ cost: parsed.cost,
89
97
  });
90
98
  }
91
99
  toOpenAIMessage() {
@@ -154,7 +162,7 @@ export class AssistantMessage extends BaseMessage {
154
162
  const blocks = [];
155
163
  // Thinking blocks must come first (Anthropic requires this ordering)
156
164
  if (hasThinking) {
157
- for (const block of this._thinkingBlocks) {
165
+ for (const block of this._thinkingBlocks ?? []) {
158
166
  blocks.push({ type: "thinking", thinking: block.text, signature: block.signature });
159
167
  }
160
168
  }
@@ -3,6 +3,7 @@ import { Message } from "ollama";
3
3
  import { ChatCompletionMessageParam } from "openai/resources";
4
4
  import type { ResponseInputItem } from "openai/resources/responses/responses.js";
5
5
  export declare class BaseMessage {
6
+ protected contentToString(content: string | unknown[] | null | undefined): string;
6
7
  }
7
8
  export interface MessageClass {
8
9
  get content(): string;
@@ -1,2 +1,7 @@
1
1
  export class BaseMessage {
2
+ contentToString(content) {
3
+ if (content === null || content === undefined)
4
+ return "";
5
+ return typeof content === "string" ? content : JSON.stringify(content);
6
+ }
2
7
  }
@@ -1,14 +1,20 @@
1
+ import { z } from "zod";
1
2
  import { BaseMessage, MessageClass } from "./BaseMessage.js";
2
3
  import { TextPart } from "../../types.js";
3
4
  import { ChatCompletionMessageParam } from "openai/resources";
4
5
  import { Content } from "@google/genai";
5
6
  import { Message } from "ollama";
6
7
  import type { ResponseInputItem } from "openai/resources/responses/responses.js";
7
- export type DeveloperMessageJSON = {
8
- role: "developer";
9
- content: string | Array<TextPart>;
10
- name: string | undefined;
11
- };
8
+ export declare const DeveloperMessageJSONSchema: z.ZodObject<{
9
+ role: z.ZodLiteral<"developer">;
10
+ content: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodObject<{
11
+ type: z.ZodLiteral<"text">;
12
+ text: z.ZodString;
13
+ }, z.core.$strip>>]>;
14
+ name: z.ZodOptional<z.ZodString>;
15
+ rawData: z.ZodOptional<z.ZodAny>;
16
+ }, z.core.$strip>;
17
+ export type DeveloperMessageJSON = z.infer<typeof DeveloperMessageJSONSchema>;
12
18
  export declare class DeveloperMessage extends BaseMessage implements MessageClass {
13
19
  _role: "developer";
14
20
  _content: string | Array<TextPart>;
@@ -24,7 +30,7 @@ export declare class DeveloperMessage extends BaseMessage implements MessageClas
24
30
  get name(): string | undefined;
25
31
  get rawData(): any;
26
32
  toJSON(): DeveloperMessageJSON;
27
- static fromJSON(json: any): DeveloperMessage;
33
+ static fromJSON(json: unknown): DeveloperMessage;
28
34
  toOpenAIMessage(): ChatCompletionMessageParam;
29
35
  toOpenAIResponseInputItem(): ResponseInputItem;
30
36
  toGoogleMessage(): Content;
@@ -1,4 +1,12 @@
1
+ import { z } from "zod";
1
2
  import { BaseMessage } from "./BaseMessage.js";
3
+ import { TextPartSchema } from "../../types.js";
4
+ export const DeveloperMessageJSONSchema = z.object({
5
+ role: z.literal("developer"),
6
+ content: z.union([z.string(), z.array(TextPartSchema)]),
7
+ name: z.string().optional(),
8
+ rawData: z.any().optional(),
9
+ });
2
10
  export class DeveloperMessage extends BaseMessage {
3
11
  _role = "developer";
4
12
  _content;
@@ -11,9 +19,7 @@ export class DeveloperMessage extends BaseMessage {
11
19
  this._rawData = options.rawData;
12
20
  }
13
21
  get content() {
14
- return typeof this._content === "string"
15
- ? this._content
16
- : JSON.stringify(this._content);
22
+ return this.contentToString(this._content);
17
23
  }
18
24
  set content(value) {
19
25
  this._content = value;
@@ -35,9 +41,10 @@ export class DeveloperMessage extends BaseMessage {
35
41
  };
36
42
  }
37
43
  static fromJSON(json) {
38
- return new DeveloperMessage(json.content, {
39
- name: json.name,
40
- rawData: json.rawData,
44
+ const parsed = DeveloperMessageJSONSchema.parse(json);
45
+ return new DeveloperMessage(parsed.content, {
46
+ name: parsed.name,
47
+ rawData: parsed.rawData,
41
48
  });
42
49
  }
43
50
  toOpenAIMessage() {
@@ -1,14 +1,20 @@
1
+ import { z } from "zod";
1
2
  import { BaseMessage, MessageClass } from "./BaseMessage.js";
2
3
  import { TextPart } from "../../types.js";
3
4
  import { ChatCompletionMessageParam } from "openai/resources";
4
5
  import { Content } from "@google/genai";
5
6
  import { Message } from "ollama";
6
7
  import type { ResponseInputItem } from "openai/resources/responses/responses.js";
7
- export type SystemMessageJSON = {
8
- role: "system";
9
- content: string | Array<TextPart>;
10
- name: string | undefined;
11
- };
8
+ export declare const SystemMessageJSONSchema: z.ZodObject<{
9
+ role: z.ZodLiteral<"system">;
10
+ content: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodObject<{
11
+ type: z.ZodLiteral<"text">;
12
+ text: z.ZodString;
13
+ }, z.core.$strip>>]>;
14
+ name: z.ZodOptional<z.ZodString>;
15
+ rawData: z.ZodOptional<z.ZodAny>;
16
+ }, z.core.$strip>;
17
+ export type SystemMessageJSON = z.infer<typeof SystemMessageJSONSchema>;
12
18
  export declare class SystemMessage extends BaseMessage implements MessageClass {
13
19
  _role: "system";
14
20
  _content: string | Array<TextPart>;
@@ -24,7 +30,7 @@ export declare class SystemMessage extends BaseMessage implements MessageClass {
24
30
  get name(): string | undefined;
25
31
  get rawData(): any;
26
32
  toJSON(): SystemMessageJSON;
27
- static fromJSON(json: any): SystemMessage;
33
+ static fromJSON(json: unknown): SystemMessage;
28
34
  toOpenAIMessage(): ChatCompletionMessageParam;
29
35
  toOpenAIResponseInputItem(): ResponseInputItem;
30
36
  toGoogleMessage(): Content;
@@ -1,4 +1,12 @@
1
+ import { z } from "zod";
1
2
  import { BaseMessage } from "./BaseMessage.js";
3
+ import { TextPartSchema } from "../../types.js";
4
+ export const SystemMessageJSONSchema = z.object({
5
+ role: z.literal("system"),
6
+ content: z.union([z.string(), z.array(TextPartSchema)]),
7
+ name: z.string().optional(),
8
+ rawData: z.any().optional(),
9
+ });
2
10
  export class SystemMessage extends BaseMessage {
3
11
  _role = "system";
4
12
  _content;
@@ -11,9 +19,7 @@ export class SystemMessage extends BaseMessage {
11
19
  this._rawData = options.rawData;
12
20
  }
13
21
  get content() {
14
- return typeof this._content === "string"
15
- ? this._content
16
- : JSON.stringify(this._content);
22
+ return this.contentToString(this._content);
17
23
  }
18
24
  set content(value) {
19
25
  this._content = value;
@@ -35,9 +41,10 @@ export class SystemMessage extends BaseMessage {
35
41
  };
36
42
  }
37
43
  static fromJSON(json) {
38
- return new SystemMessage(json.content, {
39
- name: json.name,
40
- rawData: json.rawData,
44
+ const parsed = SystemMessageJSONSchema.parse(json);
45
+ return new SystemMessage(parsed.content, {
46
+ name: parsed.name,
47
+ rawData: parsed.rawData,
41
48
  });
42
49
  }
43
50
  toOpenAIMessage() {
@@ -1,15 +1,21 @@
1
+ import { z } from "zod";
1
2
  import { BaseMessage, MessageClass } from "./BaseMessage.js";
2
3
  import { TextPart } from "../../types.js";
3
4
  import { ChatCompletionMessageParam } from "openai/resources";
4
5
  import { Content } from "@google/genai";
5
6
  import { Message } from "ollama";
6
7
  import type { ResponseInputItem } from "openai/resources/responses/responses.js";
7
- export type ToolMessageJSON = {
8
- role: "tool";
9
- content: string | Array<TextPart>;
10
- name: string;
11
- tool_call_id: string;
12
- };
8
+ export declare const ToolMessageJSONSchema: z.ZodObject<{
9
+ role: z.ZodLiteral<"tool">;
10
+ content: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodObject<{
11
+ type: z.ZodLiteral<"text">;
12
+ text: z.ZodString;
13
+ }, z.core.$strip>>]>;
14
+ name: z.ZodString;
15
+ tool_call_id: z.ZodDefault<z.ZodString>;
16
+ rawData: z.ZodOptional<z.ZodAny>;
17
+ }, z.core.$strip>;
18
+ export type ToolMessageJSON = z.infer<typeof ToolMessageJSONSchema>;
13
19
  export declare class ToolMessage extends BaseMessage implements MessageClass {
14
20
  _role: "tool";
15
21
  _content: string | Array<TextPart>;
@@ -28,7 +34,7 @@ export declare class ToolMessage extends BaseMessage implements MessageClass {
28
34
  get tool_call_id(): string;
29
35
  get rawData(): any;
30
36
  toJSON(): ToolMessageJSON;
31
- static fromJSON(json: any): ToolMessage;
37
+ static fromJSON(json: unknown): ToolMessage;
32
38
  toOpenAIMessage(): ChatCompletionMessageParam;
33
39
  toOpenAIResponseInputItem(): ResponseInputItem;
34
40
  toGoogleMessage(): Content;
@@ -1,4 +1,13 @@
1
+ import { z } from "zod";
1
2
  import { BaseMessage } from "./BaseMessage.js";
3
+ import { TextPartSchema } from "../../types.js";
4
+ export const ToolMessageJSONSchema = z.object({
5
+ role: z.literal("tool"),
6
+ content: z.union([z.string(), z.array(TextPartSchema)]),
7
+ name: z.string(),
8
+ tool_call_id: z.string().default(""),
9
+ rawData: z.any().optional(),
10
+ });
2
11
  export class ToolMessage extends BaseMessage {
3
12
  _role = "tool";
4
13
  _content;
@@ -13,9 +22,7 @@ export class ToolMessage extends BaseMessage {
13
22
  this._name = options.name;
14
23
  }
15
24
  get content() {
16
- return typeof this._content === "string"
17
- ? this._content
18
- : JSON.stringify(this._content);
25
+ return this.contentToString(this._content);
19
26
  }
20
27
  set content(value) {
21
28
  this._content = value;
@@ -41,10 +48,11 @@ export class ToolMessage extends BaseMessage {
41
48
  };
42
49
  }
43
50
  static fromJSON(json) {
44
- return new ToolMessage(json.content, {
45
- tool_call_id: json.tool_call_id,
46
- name: json.name,
47
- rawData: json.rawData,
51
+ const parsed = ToolMessageJSONSchema.parse(json);
52
+ return new ToolMessage(parsed.content, {
53
+ tool_call_id: parsed.tool_call_id,
54
+ name: parsed.name,
55
+ rawData: parsed.rawData,
48
56
  });
49
57
  }
50
58
  toOpenAIMessage() {
@@ -1,13 +1,16 @@
1
+ import { z } from "zod";
1
2
  import { BaseMessage, MessageClass } from "./BaseMessage.js";
2
3
  import { ChatCompletionMessageParam } from "openai/resources";
3
4
  import { Content } from "@google/genai";
4
5
  import { Message } from "ollama";
5
6
  import type { ResponseInputItem } from "openai/resources/responses/responses.js";
6
- export type UserMessageJSON = {
7
- role: "user";
8
- content: string;
9
- name: string | undefined;
10
- };
7
+ export declare const UserMessageJSONSchema: z.ZodObject<{
8
+ role: z.ZodLiteral<"user">;
9
+ content: z.ZodString;
10
+ name: z.ZodOptional<z.ZodString>;
11
+ rawData: z.ZodOptional<z.ZodAny>;
12
+ }, z.core.$strip>;
13
+ export type UserMessageJSON = z.infer<typeof UserMessageJSONSchema>;
11
14
  export declare class UserMessage extends BaseMessage implements MessageClass {
12
15
  _role: "user";
13
16
  _content: string;
@@ -23,7 +26,7 @@ export declare class UserMessage extends BaseMessage implements MessageClass {
23
26
  get name(): string | undefined;
24
27
  get rawData(): any;
25
28
  toJSON(): UserMessageJSON;
26
- static fromJSON(json: any): UserMessage;
29
+ static fromJSON(json: unknown): UserMessage;
27
30
  toOpenAIMessage(): ChatCompletionMessageParam;
28
31
  toOpenAIResponseInputItem(): ResponseInputItem;
29
32
  toGoogleMessage(): Content;
@@ -1,4 +1,11 @@
1
+ import { z } from "zod";
1
2
  import { BaseMessage } from "./BaseMessage.js";
3
+ export const UserMessageJSONSchema = z.object({
4
+ role: z.literal("user"),
5
+ content: z.string(),
6
+ name: z.string().optional(),
7
+ rawData: z.any().optional(),
8
+ });
2
9
  export class UserMessage extends BaseMessage {
3
10
  _role = "user";
4
11
  _content;
@@ -33,9 +40,10 @@ export class UserMessage extends BaseMessage {
33
40
  };
34
41
  }
35
42
  static fromJSON(json) {
36
- return new UserMessage(json.content, {
37
- name: json.name,
38
- rawData: json.rawData,
43
+ const parsed = UserMessageJSONSchema.parse(json);
44
+ return new UserMessage(parsed.content, {
45
+ name: parsed.name,
46
+ rawData: parsed.rawData,
39
47
  });
40
48
  }
41
49
  toOpenAIMessage() {
@@ -22,7 +22,7 @@ export function messageFromJSON(json) {
22
22
  case "tool":
23
23
  return ToolMessage.fromJSON(json);
24
24
  default:
25
- throw new Error(`Unknown message: ${JSON.stringify(json)}`);
25
+ throw new Error(`Unknown message role: ${json?.role}`);
26
26
  }
27
27
  }
28
28
  export function userMessage(content, options = {}) {
package/dist/client.d.ts CHANGED
@@ -2,10 +2,7 @@ export * from "./clients/anthropic.js";
2
2
  export * from "./clients/google.js";
3
3
  export * from "./clients/openai.js";
4
4
  export * from "./clients/openaiResponses.js";
5
- import { SmolAnthropic } from "./clients/anthropic.js";
6
- import { SmolGoogle } from "./clients/google.js";
7
- import { SmolOpenAi } from "./clients/openai.js";
8
- import { SmolOpenAiResponses } from "./clients/openaiResponses.js";
9
- import { SmolConfig } from "./types.js";
10
- import { SmolOllama } from "./clients/ollama.js";
11
- export declare function getClient(config: SmolConfig): SmolAnthropic | SmolGoogle | SmolOpenAi | SmolOpenAiResponses | SmolOllama;
5
+ import { BaseClient } from "./clients/baseClient.js";
6
+ import { ResolvedSmolConfig } from "./types.js";
7
+ export declare function registerProvider(providerName: string, clientClass: typeof BaseClient): void;
8
+ export declare function getClient(config: ResolvedSmolConfig): BaseClient;
package/dist/client.js CHANGED
@@ -4,19 +4,18 @@ export * from "./clients/openai.js";
4
4
  export * from "./clients/openaiResponses.js";
5
5
  import { SmolAnthropic } from "./clients/anthropic.js";
6
6
  import { SmolGoogle } from "./clients/google.js";
7
+ import { SmolOllama } from "./clients/ollama.js";
7
8
  import { SmolOpenAi } from "./clients/openai.js";
8
9
  import { SmolOpenAiResponses } from "./clients/openaiResponses.js";
9
10
  import { getModel, isTextModel } from "./models.js";
10
11
  import { SmolError } from "./smolError.js";
11
- import { getLogger } from "./logger.js";
12
- import { SmolOllama } from "./clients/ollama.js";
13
- import { Model } from "./model.js";
12
+ const registeredProviders = {};
13
+ export function registerProvider(providerName, clientClass) {
14
+ registeredProviders[providerName] = clientClass;
15
+ }
14
16
  export function getClient(config) {
15
- // Initialize logger singleton with desired log level
16
- const logger = getLogger(config.logLevel);
17
- // Resolve ModelConfig to a concrete model name
18
- const modelName = new Model(config.model).getResolvedModel();
19
17
  let provider = config.provider;
18
+ const modelName = config.model;
20
19
  if (!provider) {
21
20
  const model = getModel(modelName);
22
21
  if (model === undefined) {
@@ -55,6 +54,10 @@ export function getClient(config) {
55
54
  case "ollama":
56
55
  return new SmolOllama(clientConfig);
57
56
  default:
57
+ if (provider in registeredProviders) {
58
+ const ClientClass = registeredProviders[provider];
59
+ return new ClientClass(clientConfig);
60
+ }
58
61
  throw new SmolError(`Model provider ${provider} is not supported.`);
59
62
  }
60
63
  }
@@ -1,9 +1,9 @@
1
1
  import { StatelogClient } from "../statelogClient.js";
2
- import { PromptConfig, PromptResult, Result, SmolClient, SmolConfig, StreamChunk } from "../types.js";
2
+ import { PromptConfig, PromptResult, ResolvedSmolConfig, Result, SmolClient, StreamChunk } from "../types.js";
3
3
  export declare class BaseClient implements SmolClient {
4
- protected config: SmolConfig;
4
+ protected config: ResolvedSmolConfig;
5
5
  protected statelogClient?: StatelogClient;
6
- constructor(config: SmolConfig);
6
+ constructor(config: ResolvedSmolConfig);
7
7
  protected getAbortSignal(promptConfig: PromptConfig): AbortSignal | undefined;
8
8
  protected isAbortError(err: unknown): boolean;
9
9
  text(promptConfig: Omit<PromptConfig, "stream">): Promise<Result<PromptResult>>;
@@ -24,10 +24,9 @@ export declare class BaseClient implements SmolClient {
24
24
  continue: boolean;
25
25
  newPromptConfig: PromptConfig;
26
26
  };
27
- extractResponse(promptConfig: PromptConfig, rawValue: any, schema: any): any;
27
+ extractResponse(promptConfig: PromptConfig, rawValue: any, schema: any, depth?: number): any;
28
28
  textWithRetry(promptConfig: PromptConfig, retries: number): Promise<Result<PromptResult>>;
29
29
  _textSync(promptConfig: PromptConfig): Promise<Result<PromptResult>>;
30
- prompt(text: string, promptConfig?: PromptConfig): Promise<Result<PromptResult>> | AsyncGenerator<StreamChunk>;
31
30
  textStream(config: PromptConfig): AsyncGenerator<StreamChunk>;
32
31
  _textStream(config: PromptConfig): AsyncGenerator<StreamChunk>;
33
32
  }