smoltalk 0.2.1 → 0.2.2

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.
@@ -141,17 +141,14 @@ export class BaseClient {
141
141
  if (rawValue && typeof rawValue === "object" && rawValue.type === "object" && rawValue.properties) {
142
142
  return this.extractResponse(promptConfig, rawValue.properties, schema, depth + 1);
143
143
  }
144
- // 2. String → try JSON.parse (after stripping markdown fences), then recurse.
145
- // Throws SmolStructuredOutputError if the string isn't valid JSON; the
146
- // textWithRetry caller catches this and retries with a validation hint.
144
+ // 2. String → try JSON.parse, then recurse
147
145
  if (typeof rawValue === "string") {
148
146
  const stripped = rawValue
149
147
  .trim()
150
148
  .replace(/^```json\s*/, "")
151
149
  .replace(/```\s*$/, "");
152
- let parsed;
153
150
  try {
154
- parsed = JSON.parse(stripped);
151
+ return this.extractResponse(promptConfig, JSON.parse(stripped), schema, depth + 1);
155
152
  }
156
153
  catch (err) {
157
154
  const logger = getLogger();
@@ -160,9 +157,8 @@ export class BaseClient {
160
157
  rawValue: stripped,
161
158
  });
162
159
  this.statelogClient?.debug("extractResponse: failed to parse JSON from string", { error: err.message });
163
- throw new SmolStructuredOutputError(`Response did not parse as JSON: ${err.message}`);
164
160
  }
165
- return this.extractResponse(promptConfig, parsed, schema, depth + 1);
161
+ return rawValue;
166
162
  }
167
163
  // 3. Null/undefined/primitive — nothing to unwrap
168
164
  if (rawValue == null || typeof rawValue !== "object") {
@@ -208,7 +204,8 @@ export class BaseClient {
208
204
  if (result.value.toolCalls.length > 0) {
209
205
  return result;
210
206
  }
211
- if (!promptConfig.responseFormat) {
207
+ if (!promptConfig.responseFormat ||
208
+ !promptConfig.responseFormatOptions?.strict) {
212
209
  return result;
213
210
  }
214
211
  if (!("output" in result.value)) {
@@ -219,9 +216,14 @@ export class BaseClient {
219
216
  return this.textWithRetry({ ...promptConfig, messages: retryMessages }, retries - 1);
220
217
  }
221
218
  const { output } = result.value;
222
- if (output !== null && retries > 0) {
219
+ if (output !== null &&
220
+ promptConfig.responseFormat &&
221
+ promptConfig.responseFormatOptions?.strict &&
222
+ retries > 0) {
223
+ const allowExtraKeys = promptConfig.responseFormatOptions?.allowExtraKeys ?? false;
223
224
  try {
224
- const parseResult = this.extractResponse(promptConfig, output, promptConfig.responseFormat);
225
+ const parsed = JSON.parse(output);
226
+ const parseResult = this.extractResponse(promptConfig, parsed, promptConfig.responseFormat);
225
227
  return success({
226
228
  ...result.value,
227
229
  output: parseResult,
@@ -64,7 +64,6 @@ export class SmolOpenAi extends BaseClient {
64
64
  json_schema: {
65
65
  name: config.responseFormatOptions?.name || "response",
66
66
  schema: config.responseFormat.toJSONSchema(),
67
- strict: !!config.responseFormatOptions?.strict,
68
67
  },
69
68
  };
70
69
  }
@@ -76,7 +76,6 @@ export class SmolOpenAiResponses extends BaseClient {
76
76
  type: "json_schema",
77
77
  name: config.responseFormatOptions?.name || "response",
78
78
  schema: config.responseFormat.toJSONSchema(),
79
- strict: !!config.responseFormatOptions?.strict,
80
79
  },
81
80
  };
82
81
  }
@@ -1,18 +1,10 @@
1
1
  import { PromptResult, SmolConfig, StreamChunk } from "./types.js";
2
2
  import { Result } from "./types/result.js";
3
- import type { z, ZodType } from "zod";
4
3
  export declare function text(config: SmolConfig & {
5
4
  stream: true;
6
5
  }): AsyncGenerator<StreamChunk>;
7
- export declare function text<S extends ZodType>(config: Omit<SmolConfig, "responseFormat"> & {
8
- responseFormat: S;
9
- stream?: false;
10
- }): Promise<Result<PromptResult<z.infer<S>>>>;
11
6
  export declare function text(config: SmolConfig & {
12
7
  stream?: false;
13
8
  }): Promise<Result<PromptResult>>;
14
- export declare function textSync<S extends ZodType>(config: Omit<SmolConfig, "responseFormat"> & {
15
- responseFormat: S;
16
- }): Promise<Result<PromptResult<z.infer<S>>>>;
17
9
  export declare function textSync(config: SmolConfig): Promise<Result<PromptResult>>;
18
10
  export declare function textStream(config: SmolConfig): AsyncGenerator<StreamChunk>;
package/dist/types.d.ts CHANGED
@@ -92,15 +92,15 @@ export type ToolLoopDetection = {
92
92
  intervention?: "remove-tool" | "remove-all-tools" | "throw-error" | "halt-execution";
93
93
  excludeTools?: string[];
94
94
  };
95
- export type PromptResult<T = string> = {
96
- output: T | null;
95
+ export type PromptResult = {
96
+ output: string | null;
97
97
  toolCalls: ToolCall[];
98
98
  thinkingBlocks?: ThinkingBlock[];
99
99
  usage?: TokenUsage;
100
100
  cost?: CostEstimate;
101
101
  model?: ModelName;
102
102
  };
103
- export declare function promptResult<T = string>({ output, toolCalls, thinkingBlocks, usage, cost, model, }: Partial<PromptResult<T>>): PromptResult<T>;
103
+ export declare function promptResult({ output, toolCalls, thinkingBlocks, usage, cost, model, }: Partial<PromptResult>): PromptResult;
104
104
  export type StreamChunk = {
105
105
  type: "text";
106
106
  text: string;
package/dist/types.js CHANGED
@@ -4,7 +4,7 @@ export * from "./types/costEstimate.js";
4
4
  export * from "./types/tokenUsage.js";
5
5
  export function promptResult({ output, toolCalls, thinkingBlocks, usage, cost, model, }) {
6
6
  return {
7
- output: (output ?? null),
7
+ output: output || null,
8
8
  toolCalls: toolCalls || [],
9
9
  thinkingBlocks: thinkingBlocks,
10
10
  usage,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "smoltalk",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "A common interface for LLM APIs",
5
5
  "homepage": "https://github.com/egonSchiele/smoltalk",
6
6
  "files": [