smoltalk 0.4.2 → 0.5.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.
- package/README.md +139 -0
- package/dist/classes/message/AssistantMessage.d.ts +1 -0
- package/dist/client.js +5 -3
- package/dist/clients/anthropic.d.ts +3 -1
- package/dist/clients/anthropic.js +65 -10
- package/dist/clients/baseClient.js +11 -1
- package/dist/clients/google.d.ts +3 -0
- package/dist/clients/google.js +76 -7
- package/dist/clients/ollama.js +1 -1
- package/dist/clients/openai.js +1 -1
- package/dist/clients/openaiResponses.d.ts +3 -0
- package/dist/clients/openaiResponses.js +54 -4
- package/dist/embed/openai.js +3 -3
- package/dist/embed.d.ts +5 -2
- package/dist/embed.js +14 -3
- package/dist/image/google.js +3 -3
- package/dist/image/openai.js +6 -6
- package/dist/image.d.ts +5 -2
- package/dist/image.js +14 -3
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/model.d.ts +4 -2
- package/dist/model.js +7 -5
- package/dist/modelData.d.ts +40 -0
- package/dist/modelData.js +222 -0
- package/dist/models.d.ts +658 -760
- package/dist/models.js +836 -60
- package/dist/types/costEstimate.d.ts +2 -0
- package/dist/types/costEstimate.js +1 -0
- package/dist/types.d.ts +30 -1
- package/dist/types.js +2 -1
- package/dist/util/hostedTools.d.ts +19 -0
- package/dist/util/hostedTools.js +104 -0
- package/dist/util/provider.d.ts +2 -1
- package/dist/util/provider.js +2 -2
- package/package.json +7 -2
|
@@ -4,6 +4,7 @@ export type CostEstimate = {
|
|
|
4
4
|
outputCost: number;
|
|
5
5
|
cachedInputCost?: number;
|
|
6
6
|
cacheCreationInputCost?: number;
|
|
7
|
+
hostedToolsCost?: number;
|
|
7
8
|
totalCost: number;
|
|
8
9
|
currency: string;
|
|
9
10
|
};
|
|
@@ -12,6 +13,7 @@ export declare const CostEstimateSchema: z.ZodObject<{
|
|
|
12
13
|
outputCost: z.ZodNumber;
|
|
13
14
|
cachedInputCost: z.ZodOptional<z.ZodNumber>;
|
|
14
15
|
cacheCreationInputCost: z.ZodOptional<z.ZodNumber>;
|
|
16
|
+
hostedToolsCost: z.ZodOptional<z.ZodNumber>;
|
|
15
17
|
totalCost: z.ZodNumber;
|
|
16
18
|
currency: z.ZodString;
|
|
17
19
|
}, z.core.$strip>;
|
package/dist/types.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { Message } from "./classes/message/index.js";
|
|
|
5
5
|
import { ToolCall } from "./classes/ToolCall.js";
|
|
6
6
|
import { Model } from "./model.js";
|
|
7
7
|
import { ModelName } from "./models.js";
|
|
8
|
+
import type { ModelDataBlob } from "./modelData.js";
|
|
8
9
|
import { Result } from "./types/result.js";
|
|
9
10
|
import { TokenUsage } from "./types/tokenUsage.js";
|
|
10
11
|
import { CostEstimate } from "./types/costEstimate.js";
|
|
@@ -44,6 +45,8 @@ export type SmolConfig = {
|
|
|
44
45
|
}>;
|
|
45
46
|
/** Arbitrary metadata passed to custom model providers. */
|
|
46
47
|
metadata?: Record<string, any>;
|
|
48
|
+
/** Refreshed model/hosted-tool data (from refreshModels) to layer over the baked-in registry for this call. */
|
|
49
|
+
modelData?: ModelDataBlob;
|
|
47
50
|
/** The conversation messages to send to the model. */
|
|
48
51
|
messages: Message[];
|
|
49
52
|
/** Tools (functions) the model can call. */
|
|
@@ -52,6 +55,10 @@ export type SmolConfig = {
|
|
|
52
55
|
description?: string;
|
|
53
56
|
schema: ZodType;
|
|
54
57
|
}[];
|
|
58
|
+
/** Provider hosted tools (server-side) to enable for this call, by capability
|
|
59
|
+
* name (catalog category), e.g. ["web_search"]. Distinct from `tools`
|
|
60
|
+
* (client functions) — hosted tools run server-side and can't be intercepted. */
|
|
61
|
+
hostedTools?: string[];
|
|
55
62
|
/** Maximum number of tokens the model can generate in its response. */
|
|
56
63
|
maxTokens?: number;
|
|
57
64
|
/** Sampling temperature (0-2). (OpenAI only) */
|
|
@@ -96,6 +103,27 @@ export type ToolLoopDetection = {
|
|
|
96
103
|
intervention?: "remove-tool" | "remove-all-tools" | "throw-error" | "halt-execution";
|
|
97
104
|
excludeTools?: string[];
|
|
98
105
|
};
|
|
106
|
+
export type WebSearchSource = {
|
|
107
|
+
url: string;
|
|
108
|
+
title?: string;
|
|
109
|
+
snippet?: string;
|
|
110
|
+
};
|
|
111
|
+
export type WebSearchCitation = {
|
|
112
|
+
url: string;
|
|
113
|
+
title?: string;
|
|
114
|
+
startIndex?: number;
|
|
115
|
+
endIndex?: number;
|
|
116
|
+
};
|
|
117
|
+
export type HostedToolResult = {
|
|
118
|
+
tool: string;
|
|
119
|
+
provider: string;
|
|
120
|
+
queries?: string[];
|
|
121
|
+
sources?: WebSearchSource[];
|
|
122
|
+
citations?: WebSearchCitation[];
|
|
123
|
+
callCount?: number;
|
|
124
|
+
estimatedCost?: number;
|
|
125
|
+
raw?: unknown;
|
|
126
|
+
};
|
|
99
127
|
export type PromptResult = {
|
|
100
128
|
output: string | null;
|
|
101
129
|
toolCalls: ToolCall[];
|
|
@@ -103,8 +131,9 @@ export type PromptResult = {
|
|
|
103
131
|
usage?: TokenUsage;
|
|
104
132
|
cost?: CostEstimate;
|
|
105
133
|
model?: ModelName;
|
|
134
|
+
hostedToolResults?: HostedToolResult[];
|
|
106
135
|
};
|
|
107
|
-
export declare function promptResult({ output, toolCalls, thinkingBlocks, usage, cost, model, }: Partial<PromptResult>): PromptResult;
|
|
136
|
+
export declare function promptResult({ output, toolCalls, thinkingBlocks, usage, cost, model, hostedToolResults, }: Partial<PromptResult>): PromptResult;
|
|
108
137
|
export type StreamChunk = {
|
|
109
138
|
type: "text";
|
|
110
139
|
text: string;
|
package/dist/types.js
CHANGED
|
@@ -2,7 +2,7 @@ export * from "./types/result.js";
|
|
|
2
2
|
import z from "zod";
|
|
3
3
|
export * from "./types/costEstimate.js";
|
|
4
4
|
export * from "./types/tokenUsage.js";
|
|
5
|
-
export function promptResult({ output, toolCalls, thinkingBlocks, usage, cost, model, }) {
|
|
5
|
+
export function promptResult({ output, toolCalls, thinkingBlocks, usage, cost, model, hostedToolResults, }) {
|
|
6
6
|
return {
|
|
7
7
|
output: output || null,
|
|
8
8
|
toolCalls: toolCalls || [],
|
|
@@ -10,6 +10,7 @@ export function promptResult({ output, toolCalls, thinkingBlocks, usage, cost, m
|
|
|
10
10
|
usage,
|
|
11
11
|
cost,
|
|
12
12
|
model,
|
|
13
|
+
hostedToolResults,
|
|
13
14
|
};
|
|
14
15
|
}
|
|
15
16
|
export const TextPartSchema = z.object({
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ModelDataBlob } from "../modelData.js";
|
|
2
|
+
import type { CostEstimate } from "../types/costEstimate.js";
|
|
3
|
+
import type { HostedToolResult, WebSearchSource, WebSearchCitation } from "../types.js";
|
|
4
|
+
export declare const WEB_SEARCH = "web_search";
|
|
5
|
+
export declare const IMPLEMENTED_HOSTED_TOOLS: Set<string>;
|
|
6
|
+
export declare function validateHostedTools(requested: string[] | undefined, model: string, modelData?: ModelDataBlob): string | null;
|
|
7
|
+
export declare function estimateHostedToolCost(result: HostedToolResult, model: string, modelData?: ModelDataBlob): number | undefined;
|
|
8
|
+
export declare function foldHostedToolCost(cost: CostEstimate | undefined, results: HostedToolResult[]): CostEstimate | undefined;
|
|
9
|
+
export declare function webSearchResult(provider: string, parts: {
|
|
10
|
+
queries?: string[];
|
|
11
|
+
sources?: WebSearchSource[];
|
|
12
|
+
citations?: WebSearchCitation[];
|
|
13
|
+
callCount?: number;
|
|
14
|
+
raw?: unknown;
|
|
15
|
+
}): HostedToolResult;
|
|
16
|
+
export declare function applyHostedToolCost(results: HostedToolResult[], cost: CostEstimate | undefined, model: string, modelData?: ModelDataBlob): {
|
|
17
|
+
results: HostedToolResult[];
|
|
18
|
+
cost: CostEstimate | undefined;
|
|
19
|
+
};
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { getHostedTools, hostedToolPricingFor } from "../models.js";
|
|
2
|
+
import { getModel } from "../models.js";
|
|
3
|
+
import { round } from "./util.js";
|
|
4
|
+
export const WEB_SEARCH = "web_search";
|
|
5
|
+
// Capabilities whose runtime translation/parsing smoltalk actually implements.
|
|
6
|
+
export const IMPLEMENTED_HOSTED_TOOLS = new Set([WEB_SEARCH]);
|
|
7
|
+
// Returns an error message if any requested capability is unusable for this
|
|
8
|
+
// model, else null. Capabilities are matched against the catalog `category`.
|
|
9
|
+
export function validateHostedTools(requested, model, modelData) {
|
|
10
|
+
if (!requested || requested.length === 0) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
const allCategories = new Set(getHostedTools({ includeDisabled: true, modelData }).map((t) => t.category));
|
|
14
|
+
const availableCategories = new Set(getHostedTools({ model, modelData }).map((t) => t.category));
|
|
15
|
+
for (const name of requested) {
|
|
16
|
+
if (!IMPLEMENTED_HOSTED_TOOLS.has(name)) {
|
|
17
|
+
if (allCategories.has(name)) {
|
|
18
|
+
return `Hosted tool "${name}" is in the catalog but not yet supported by smoltalk at runtime.`;
|
|
19
|
+
}
|
|
20
|
+
return `Unknown hosted tool "${name}".`;
|
|
21
|
+
}
|
|
22
|
+
if (!availableCategories.has(name)) {
|
|
23
|
+
const provider = getModel(model, modelData)?.provider ?? "unknown";
|
|
24
|
+
return `${name} is a hosted capability; ${model} (${provider}) doesn't offer it — pass a search function as a tool instead.`;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
// callCount x catalog price for the capability on this model. Only per_call
|
|
30
|
+
// pricing yields a number (web search); undefined otherwise.
|
|
31
|
+
export function estimateHostedToolCost(result, model, modelData) {
|
|
32
|
+
if (!result.callCount) {
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
const tools = getHostedTools({ model, includeDisabled: true, modelData });
|
|
36
|
+
const tool = tools.find((t) => t.category === result.tool && t.provider === result.provider);
|
|
37
|
+
if (!tool) {
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
const price = hostedToolPricingFor(tool, model);
|
|
41
|
+
if (!price || price.unit !== "per_call" || price.amount === undefined) {
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
return round(result.callCount * price.amount, 6);
|
|
45
|
+
}
|
|
46
|
+
// Fold per-result estimatedCost into a CostEstimate (hostedToolsCost + totalCost).
|
|
47
|
+
export function foldHostedToolCost(cost, results) {
|
|
48
|
+
let hosted = 0;
|
|
49
|
+
for (const r of results) {
|
|
50
|
+
if (r.estimatedCost) {
|
|
51
|
+
hosted += r.estimatedCost;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (hosted === 0) {
|
|
55
|
+
return cost;
|
|
56
|
+
}
|
|
57
|
+
const hostedRounded = round(hosted, 6);
|
|
58
|
+
if (!cost) {
|
|
59
|
+
return {
|
|
60
|
+
inputCost: 0,
|
|
61
|
+
outputCost: 0,
|
|
62
|
+
hostedToolsCost: hostedRounded,
|
|
63
|
+
totalCost: hostedRounded,
|
|
64
|
+
currency: "USD",
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
...cost,
|
|
69
|
+
hostedToolsCost: round((cost.hostedToolsCost || 0) + hosted, 6),
|
|
70
|
+
totalCost: round(cost.totalCost + hosted, 6),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
// Build a normalized web-search result, omitting empty fields. One place for the
|
|
74
|
+
// "assemble result" shape so each parser doesn't repeat it.
|
|
75
|
+
export function webSearchResult(provider, parts) {
|
|
76
|
+
const result = { tool: WEB_SEARCH, provider };
|
|
77
|
+
if (parts.queries && parts.queries.length > 0) {
|
|
78
|
+
result.queries = parts.queries;
|
|
79
|
+
}
|
|
80
|
+
if (parts.sources && parts.sources.length > 0) {
|
|
81
|
+
result.sources = parts.sources;
|
|
82
|
+
}
|
|
83
|
+
if (parts.citations && parts.citations.length > 0) {
|
|
84
|
+
result.citations = parts.citations;
|
|
85
|
+
}
|
|
86
|
+
if (parts.callCount) {
|
|
87
|
+
result.callCount = parts.callCount;
|
|
88
|
+
}
|
|
89
|
+
if (parts.raw !== undefined) {
|
|
90
|
+
result.raw = parts.raw;
|
|
91
|
+
}
|
|
92
|
+
return result;
|
|
93
|
+
}
|
|
94
|
+
// Estimate per-result cost and fold the total into the CostEstimate. One call
|
|
95
|
+
// for every client, so the estimate+fold sequence lives in exactly one place.
|
|
96
|
+
export function applyHostedToolCost(results, cost, model, modelData) {
|
|
97
|
+
for (const r of results) {
|
|
98
|
+
const est = estimateHostedToolCost(r, model, modelData);
|
|
99
|
+
if (est !== undefined) {
|
|
100
|
+
r.estimatedCost = est;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return { results, cost: foldHostedToolCost(cost, results) };
|
|
104
|
+
}
|
package/dist/util/provider.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import type { ModelDataBlob } from "../modelData.js";
|
|
1
2
|
/**
|
|
2
3
|
* Resolve the provider for a given model name.
|
|
3
4
|
* If an explicit provider is given, returns it directly.
|
|
4
5
|
* Otherwise looks up the model in the registry.
|
|
5
6
|
*/
|
|
6
|
-
export declare function resolveProvider(modelName: string, explicitProvider?: string): string;
|
|
7
|
+
export declare function resolveProvider(modelName: string, explicitProvider?: string, modelData?: ModelDataBlob): string;
|
|
7
8
|
type ApiKeyConfig = {
|
|
8
9
|
openAiApiKey?: string;
|
|
9
10
|
googleApiKey?: string;
|
package/dist/util/provider.js
CHANGED
|
@@ -5,10 +5,10 @@ import { SmolError } from "../smolError.js";
|
|
|
5
5
|
* If an explicit provider is given, returns it directly.
|
|
6
6
|
* Otherwise looks up the model in the registry.
|
|
7
7
|
*/
|
|
8
|
-
export function resolveProvider(modelName, explicitProvider) {
|
|
8
|
+
export function resolveProvider(modelName, explicitProvider, modelData) {
|
|
9
9
|
if (explicitProvider)
|
|
10
10
|
return explicitProvider;
|
|
11
|
-
const model = getModel(modelName);
|
|
11
|
+
const model = getModel(modelName, modelData);
|
|
12
12
|
if (model === undefined) {
|
|
13
13
|
throw new SmolError(`Model ${modelName} is not recognized. Please specify a known model, or explicitly set the provider option in the config.`);
|
|
14
14
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "smoltalk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "A common interface for LLM APIs",
|
|
5
5
|
"homepage": "https://github.com/egonSchiele/smoltalk",
|
|
6
6
|
"files": [
|
|
@@ -35,6 +35,9 @@
|
|
|
35
35
|
"openai": "^6.15.0",
|
|
36
36
|
"zod": "^4.3.6"
|
|
37
37
|
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"tsx": "^4.19.2"
|
|
40
|
+
},
|
|
38
41
|
"scripts": {
|
|
39
42
|
"test": "vitest --exclude=**/*.live.test.ts",
|
|
40
43
|
"test:live": "vitest run lib/clients/*.live.test.ts lib/embed/*.live.test.ts lib/image/*.live.test.ts",
|
|
@@ -42,6 +45,8 @@
|
|
|
42
45
|
"build": "rm -rf dist && tsc",
|
|
43
46
|
"start": "cd dist && node index.js",
|
|
44
47
|
"doc": "typedoc --disableSources --out docs lib && prettier docs/ --write",
|
|
45
|
-
"typecheck": "tsc --noEmit"
|
|
48
|
+
"typecheck": "tsc --noEmit",
|
|
49
|
+
"seed-data": "tsx scripts/seed-model-data.ts",
|
|
50
|
+
"refresh-data": "tsx scripts/refresh-from-modelsdev.ts"
|
|
46
51
|
}
|
|
47
52
|
}
|