extrait 0.5.3 → 0.5.4
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 +61 -0
- package/dist/conversation.d.ts +16 -3
- package/dist/index.cjs +84 -8
- package/dist/index.d.ts +1 -1
- package/dist/index.js +84 -8
- package/dist/llm.d.ts +2 -1
- package/dist/providers/openai-compatible.d.ts +1 -0
- package/dist/types.d.ts +22 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -15,6 +15,7 @@ Structured JSON extraction from LLMs with validation, repair, and streaming.
|
|
|
15
15
|
- Optional self-healing for validation failures
|
|
16
16
|
- Streaming support
|
|
17
17
|
- MCP tools
|
|
18
|
+
- Vector embeddings (OpenAI-compatible + Voyage AI)
|
|
18
19
|
|
|
19
20
|
## Installation
|
|
20
21
|
|
|
@@ -282,6 +283,64 @@ try {
|
|
|
282
283
|
}
|
|
283
284
|
```
|
|
284
285
|
|
|
286
|
+
### Embeddings
|
|
287
|
+
|
|
288
|
+
Generate vector embeddings using `llm.embed()`. It always returns `number[][]` — one vector per input string.
|
|
289
|
+
|
|
290
|
+
```typescript
|
|
291
|
+
// Create a dedicated embedder client (recommended)
|
|
292
|
+
const embedder = createLLM({
|
|
293
|
+
provider: "openai-compatible",
|
|
294
|
+
model: "text-embedding-3-small",
|
|
295
|
+
transport: { apiKey: process.env.OPENAI_API_KEY },
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
// Single string
|
|
299
|
+
const { embeddings, model, usage } = await embedder.embed("Hello world");
|
|
300
|
+
const vector: number[] = embeddings[0];
|
|
301
|
+
|
|
302
|
+
// Multiple strings in one request
|
|
303
|
+
const { embeddings } = await embedder.embed(["text one", "text two", "text three"]);
|
|
304
|
+
// embeddings[0], embeddings[1], embeddings[2] — one vector each
|
|
305
|
+
|
|
306
|
+
// Optional: override model or request extra options per call
|
|
307
|
+
const { embeddings } = await embedder.embed("Hello", {
|
|
308
|
+
model: "text-embedding-ada-002",
|
|
309
|
+
dimensions: 512, // supported by text-embedding-3-* models
|
|
310
|
+
body: { user: "user-id" }, // pass-through to provider
|
|
311
|
+
});
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
**Result shape:**
|
|
315
|
+
|
|
316
|
+
```typescript
|
|
317
|
+
{
|
|
318
|
+
embeddings: number[][]; // one vector per input
|
|
319
|
+
model: string;
|
|
320
|
+
usage?: { inputTokens?: number; totalTokens?: number };
|
|
321
|
+
raw?: unknown; // full provider response
|
|
322
|
+
}
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
**Anthropic / Voyage AI**
|
|
326
|
+
|
|
327
|
+
Anthropic does not provide a native embedding API. Their recommended solution is [Voyage AI](https://api.voyageai.com), which uses the same OpenAI-compatible format:
|
|
328
|
+
|
|
329
|
+
```typescript
|
|
330
|
+
const embedder = createLLM({
|
|
331
|
+
provider: "openai-compatible",
|
|
332
|
+
model: "voyage-3",
|
|
333
|
+
transport: {
|
|
334
|
+
baseURL: "https://api.voyageai.com",
|
|
335
|
+
apiKey: process.env.VOYAGE_API_KEY,
|
|
336
|
+
},
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
const { embeddings } = await embedder.embed(["query", "document"]);
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
Calling `llm.embed()` on an `anthropic-compatible` adapter throws a descriptive error pointing to Voyage AI.
|
|
343
|
+
|
|
285
344
|
### MCP Tools
|
|
286
345
|
|
|
287
346
|
```typescript
|
|
@@ -370,6 +429,7 @@ Available examples:
|
|
|
370
429
|
- `calculator-tool` - MCP tool integration ([calculator-tool.ts](examples/calculator-tool.ts))
|
|
371
430
|
- `image-analysis` - Multimodal structured extraction from an image file ([image-analysis.ts](examples/image-analysis.ts))
|
|
372
431
|
- `conversation` - Multi-turn conversation history and inline image messages ([conversation.ts](examples/conversation.ts))
|
|
432
|
+
- `embeddings` - Vector embeddings, cosine similarity, and semantic comparison ([embeddings.ts](examples/embeddings.ts))
|
|
373
433
|
|
|
374
434
|
Pass arguments after the example name:
|
|
375
435
|
```bash
|
|
@@ -380,6 +440,7 @@ bun run dev timeout 5000
|
|
|
380
440
|
bun run dev simple "Bun.js runtime"
|
|
381
441
|
bun run dev sentiment-analysis "I love this product."
|
|
382
442
|
bun run dev multi-step-reasoning "Why is the sky blue?"
|
|
443
|
+
bun run dev embeddings "the cat sat on the mat" "a feline rested on the rug"
|
|
383
444
|
```
|
|
384
445
|
|
|
385
446
|
## Environment Variables
|
package/dist/conversation.d.ts
CHANGED
|
@@ -1,8 +1,21 @@
|
|
|
1
1
|
import { type ImageInput } from "./image";
|
|
2
2
|
import type { LLMMessage } from "./types";
|
|
3
|
-
export
|
|
4
|
-
role: "user"
|
|
3
|
+
export type ConversationEntry = {
|
|
4
|
+
role: "user";
|
|
5
5
|
text: string;
|
|
6
6
|
images?: ImageInput[];
|
|
7
|
-
}
|
|
7
|
+
} | {
|
|
8
|
+
role: "assistant";
|
|
9
|
+
text: string;
|
|
10
|
+
images?: ImageInput[];
|
|
11
|
+
} | {
|
|
12
|
+
role: "tool_call";
|
|
13
|
+
id: string;
|
|
14
|
+
name: string;
|
|
15
|
+
arguments?: Record<string, unknown>;
|
|
16
|
+
} | {
|
|
17
|
+
role: "tool_result";
|
|
18
|
+
id: string;
|
|
19
|
+
output: unknown;
|
|
20
|
+
};
|
|
8
21
|
export declare function conversation(systemPrompt: string, entries: ConversationEntry[]): LLMMessage[];
|
package/dist/index.cjs
CHANGED
|
@@ -1606,6 +1606,7 @@ function createOpenAICompatibleAdapter(options) {
|
|
|
1606
1606
|
const fetcher = options.fetcher ?? fetch;
|
|
1607
1607
|
const path = options.path ?? "/v1/chat/completions";
|
|
1608
1608
|
const responsesPath = options.responsesPath ?? "/v1/responses";
|
|
1609
|
+
const embeddingPath = options.embeddingPath ?? "/v1/embeddings";
|
|
1609
1610
|
return {
|
|
1610
1611
|
provider: "openai-compatible",
|
|
1611
1612
|
model: options.model,
|
|
@@ -1678,6 +1679,36 @@ function createOpenAICompatibleAdapter(options) {
|
|
|
1678
1679
|
const out = { text, usage, finishReason };
|
|
1679
1680
|
callbacks.onComplete?.(out);
|
|
1680
1681
|
return out;
|
|
1682
|
+
},
|
|
1683
|
+
async embed(request) {
|
|
1684
|
+
const body = cleanUndefined({
|
|
1685
|
+
...options.defaultBody,
|
|
1686
|
+
...request.body,
|
|
1687
|
+
model: request.model ?? options.model,
|
|
1688
|
+
input: request.input,
|
|
1689
|
+
dimensions: request.dimensions,
|
|
1690
|
+
encoding_format: "float"
|
|
1691
|
+
});
|
|
1692
|
+
const response = await fetcher(buildURL(options.baseURL, embeddingPath), {
|
|
1693
|
+
method: "POST",
|
|
1694
|
+
headers: buildHeaders(options),
|
|
1695
|
+
body: JSON.stringify(body)
|
|
1696
|
+
});
|
|
1697
|
+
if (!response.ok) {
|
|
1698
|
+
const message = await response.text();
|
|
1699
|
+
throw new Error(`HTTP ${response.status}: ${message}`);
|
|
1700
|
+
}
|
|
1701
|
+
const json = await response.json();
|
|
1702
|
+
const data = json.data;
|
|
1703
|
+
if (!Array.isArray(data)) {
|
|
1704
|
+
throw new Error("Unexpected embedding response: missing data array");
|
|
1705
|
+
}
|
|
1706
|
+
return {
|
|
1707
|
+
embeddings: data.map((d) => isRecord2(d) && Array.isArray(d.embedding) ? d.embedding : []),
|
|
1708
|
+
model: pickString(json.model) ?? body.model,
|
|
1709
|
+
usage: pickUsage(json),
|
|
1710
|
+
raw: json
|
|
1711
|
+
};
|
|
1681
1712
|
}
|
|
1682
1713
|
};
|
|
1683
1714
|
}
|
|
@@ -2266,10 +2297,7 @@ function buildResponsesInput(request) {
|
|
|
2266
2297
|
return buildMessages(request);
|
|
2267
2298
|
}
|
|
2268
2299
|
function toOpenAIMessage(message) {
|
|
2269
|
-
return {
|
|
2270
|
-
role: message.role,
|
|
2271
|
-
content: message.content
|
|
2272
|
-
};
|
|
2300
|
+
return { ...message };
|
|
2273
2301
|
}
|
|
2274
2302
|
function toResponsesTools(tools) {
|
|
2275
2303
|
if (!Array.isArray(tools) || tools.length === 0) {
|
|
@@ -2737,6 +2765,9 @@ function createAnthropicCompatibleAdapter(options) {
|
|
|
2737
2765
|
const out = { text, usage, finishReason };
|
|
2738
2766
|
callbacks.onComplete?.(out);
|
|
2739
2767
|
return out;
|
|
2768
|
+
},
|
|
2769
|
+
async embed() {
|
|
2770
|
+
throw new Error("Anthropic does not provide a native embedding API. " + "Use the openai-compatible provider with Voyage AI (https://api.voyageai.com) — " + "Anthropic's recommended embedding solution, which uses the same request format.");
|
|
2740
2771
|
}
|
|
2741
2772
|
};
|
|
2742
2773
|
}
|
|
@@ -3015,6 +3046,23 @@ function toAnthropicInput(messages) {
|
|
|
3015
3046
|
continue;
|
|
3016
3047
|
}
|
|
3017
3048
|
sawNonSystem = true;
|
|
3049
|
+
if (message.role === "assistant" && Array.isArray(message.tool_calls)) {
|
|
3050
|
+
const parts = [];
|
|
3051
|
+
if (message.content)
|
|
3052
|
+
parts.push({ type: "text", text: message.content });
|
|
3053
|
+
for (const tc of message.tool_calls) {
|
|
3054
|
+
parts.push({ type: "tool_use", id: tc.id, name: tc.function.name, input: JSON.parse(tc.function.arguments) });
|
|
3055
|
+
}
|
|
3056
|
+
normalizedMessages.push({ role: "assistant", content: parts });
|
|
3057
|
+
continue;
|
|
3058
|
+
}
|
|
3059
|
+
if (message.role === "tool") {
|
|
3060
|
+
normalizedMessages.push({
|
|
3061
|
+
role: "user",
|
|
3062
|
+
content: [{ type: "tool_result", tool_use_id: message.tool_call_id, content: message.content }]
|
|
3063
|
+
});
|
|
3064
|
+
continue;
|
|
3065
|
+
}
|
|
3018
3066
|
normalizedMessages.push({
|
|
3019
3067
|
role: message.role,
|
|
3020
3068
|
content: message.content
|
|
@@ -4794,6 +4842,12 @@ function createLLM(config, registry = createDefaultProviderRegistry()) {
|
|
|
4794
4842
|
async structured(schema, prompt, options) {
|
|
4795
4843
|
const merged = mergeStructuredOptions(defaults, options);
|
|
4796
4844
|
return structured(adapter, schema, prompt, merged);
|
|
4845
|
+
},
|
|
4846
|
+
async embed(input, options = {}) {
|
|
4847
|
+
if (!adapter.embed) {
|
|
4848
|
+
throw new Error(`Provider "${adapter.provider ?? "unknown"}" does not support embeddings.`);
|
|
4849
|
+
}
|
|
4850
|
+
return adapter.embed({ ...options, input });
|
|
4797
4851
|
}
|
|
4798
4852
|
};
|
|
4799
4853
|
}
|
|
@@ -4955,10 +5009,32 @@ async function resizeImage(source, size, mimeType) {
|
|
|
4955
5009
|
function conversation(systemPrompt, entries) {
|
|
4956
5010
|
return [
|
|
4957
5011
|
{ role: "system", content: systemPrompt },
|
|
4958
|
-
...entries.map((entry) =>
|
|
4959
|
-
|
|
4960
|
-
|
|
4961
|
-
|
|
5012
|
+
...entries.map((entry) => {
|
|
5013
|
+
if (entry.role === "tool_call") {
|
|
5014
|
+
return {
|
|
5015
|
+
role: "assistant",
|
|
5016
|
+
content: "",
|
|
5017
|
+
tool_calls: [
|
|
5018
|
+
{
|
|
5019
|
+
id: entry.id,
|
|
5020
|
+
type: "function",
|
|
5021
|
+
function: { name: entry.name, arguments: JSON.stringify(entry.arguments ?? {}) }
|
|
5022
|
+
}
|
|
5023
|
+
]
|
|
5024
|
+
};
|
|
5025
|
+
}
|
|
5026
|
+
if (entry.role === "tool_result") {
|
|
5027
|
+
return {
|
|
5028
|
+
role: "tool",
|
|
5029
|
+
content: typeof entry.output === "string" ? entry.output : JSON.stringify(entry.output),
|
|
5030
|
+
tool_call_id: entry.id
|
|
5031
|
+
};
|
|
5032
|
+
}
|
|
5033
|
+
return {
|
|
5034
|
+
role: entry.role,
|
|
5035
|
+
content: entry.images && entry.images.length > 0 ? [{ type: "text", text: entry.text }, ...images(entry.images)] : entry.text
|
|
5036
|
+
};
|
|
5037
|
+
})
|
|
4962
5038
|
];
|
|
4963
5039
|
}
|
|
4964
5040
|
// src/prompt.ts
|
package/dist/index.d.ts
CHANGED
|
@@ -14,4 +14,4 @@ export { createOpenAICompatibleAdapter, type OpenAICompatibleAdapterOptions, } f
|
|
|
14
14
|
export { createAnthropicCompatibleAdapter, DEFAULT_ANTHROPIC_MAX_TOKENS, DEFAULT_ANTHROPIC_VERSION, type AnthropicCompatibleAdapterOptions, } from "./providers/anthropic-compatible";
|
|
15
15
|
export { DEFAULT_MAX_TOOL_ROUNDS } from "./providers/mcp-runtime";
|
|
16
16
|
export { createDefaultProviderRegistry, createModelAdapter, createProviderRegistry, registerBuiltinProviders, type BuiltinProviderKind, type ModelAdapterConfig, type ProviderFactory, type ProviderRegistry, type ProviderTransportConfig, } from "./providers/registry";
|
|
17
|
-
export type { CandidateDiagnostics, LLMImageContent, LLMMessageContent, LLMTextContent, ExtractJsonCandidatesOptions, ExtractionCandidate, ExtractionHeuristicsOptions, ExtractionParseHint, HTTPHeaders, LLMAdapter, LLMMessage, LLMRequest, LLMResponse, LLMStreamCallbacks, LLMStreamChunk, LLMToolCall, LLMToolDebugOptions, LLMToolExecution, LLMToolOutputTransformer, LLMToolArgumentsTransformer, LLMToolChoice, MCPCallToolParams, MCPListToolsResult, MCPToolClient, MCPToolDescriptor, MCPToolSchema, LLMUsage, MarkdownCodeBlock, MarkdownCodeOptions, ParseLLMOutputOptions, ParseLLMOutputResult, ParseTraceEvent, PipelineError, StructuredAttempt, StructuredCallOptions, StructuredDebugOptions, StructuredError, StructuredMode, StructuredOptions, StructuredPromptBuilder, StructuredPromptContext, StructuredPromptPayload, StructuredPromptResolver, StructuredPromptValue, StructuredResult, StructuredStreamData, StructuredStreamEvent, StructuredStreamInput, StructuredStreamOptions, StructuredSelfHealInput, StructuredTimeoutOptions, ThinkDiagnostics, ThinkBlock, StructuredTraceEvent, } from "./types";
|
|
17
|
+
export type { CandidateDiagnostics, EmbeddingRequest, EmbeddingResult, LLMImageContent, LLMMessageContent, LLMTextContent, ExtractJsonCandidatesOptions, ExtractionCandidate, ExtractionHeuristicsOptions, ExtractionParseHint, HTTPHeaders, LLMAdapter, LLMMessage, LLMRequest, LLMResponse, LLMStreamCallbacks, LLMStreamChunk, LLMToolCall, LLMToolCallRef, LLMToolDebugOptions, LLMToolExecution, LLMToolOutputTransformer, LLMToolArgumentsTransformer, LLMToolChoice, MCPCallToolParams, MCPListToolsResult, MCPToolClient, MCPToolDescriptor, MCPToolSchema, LLMUsage, MarkdownCodeBlock, MarkdownCodeOptions, ParseLLMOutputOptions, ParseLLMOutputResult, ParseTraceEvent, PipelineError, StructuredAttempt, StructuredCallOptions, StructuredDebugOptions, StructuredError, StructuredMode, StructuredOptions, StructuredPromptBuilder, StructuredPromptContext, StructuredPromptPayload, StructuredPromptResolver, StructuredPromptValue, StructuredResult, StructuredStreamData, StructuredStreamEvent, StructuredStreamInput, StructuredStreamOptions, StructuredSelfHealInput, StructuredTimeoutOptions, ThinkDiagnostics, ThinkBlock, StructuredTraceEvent, } from "./types";
|
package/dist/index.js
CHANGED
|
@@ -1517,6 +1517,7 @@ function createOpenAICompatibleAdapter(options) {
|
|
|
1517
1517
|
const fetcher = options.fetcher ?? fetch;
|
|
1518
1518
|
const path = options.path ?? "/v1/chat/completions";
|
|
1519
1519
|
const responsesPath = options.responsesPath ?? "/v1/responses";
|
|
1520
|
+
const embeddingPath = options.embeddingPath ?? "/v1/embeddings";
|
|
1520
1521
|
return {
|
|
1521
1522
|
provider: "openai-compatible",
|
|
1522
1523
|
model: options.model,
|
|
@@ -1589,6 +1590,36 @@ function createOpenAICompatibleAdapter(options) {
|
|
|
1589
1590
|
const out = { text, usage, finishReason };
|
|
1590
1591
|
callbacks.onComplete?.(out);
|
|
1591
1592
|
return out;
|
|
1593
|
+
},
|
|
1594
|
+
async embed(request) {
|
|
1595
|
+
const body = cleanUndefined({
|
|
1596
|
+
...options.defaultBody,
|
|
1597
|
+
...request.body,
|
|
1598
|
+
model: request.model ?? options.model,
|
|
1599
|
+
input: request.input,
|
|
1600
|
+
dimensions: request.dimensions,
|
|
1601
|
+
encoding_format: "float"
|
|
1602
|
+
});
|
|
1603
|
+
const response = await fetcher(buildURL(options.baseURL, embeddingPath), {
|
|
1604
|
+
method: "POST",
|
|
1605
|
+
headers: buildHeaders(options),
|
|
1606
|
+
body: JSON.stringify(body)
|
|
1607
|
+
});
|
|
1608
|
+
if (!response.ok) {
|
|
1609
|
+
const message = await response.text();
|
|
1610
|
+
throw new Error(`HTTP ${response.status}: ${message}`);
|
|
1611
|
+
}
|
|
1612
|
+
const json = await response.json();
|
|
1613
|
+
const data = json.data;
|
|
1614
|
+
if (!Array.isArray(data)) {
|
|
1615
|
+
throw new Error("Unexpected embedding response: missing data array");
|
|
1616
|
+
}
|
|
1617
|
+
return {
|
|
1618
|
+
embeddings: data.map((d) => isRecord2(d) && Array.isArray(d.embedding) ? d.embedding : []),
|
|
1619
|
+
model: pickString(json.model) ?? body.model,
|
|
1620
|
+
usage: pickUsage(json),
|
|
1621
|
+
raw: json
|
|
1622
|
+
};
|
|
1592
1623
|
}
|
|
1593
1624
|
};
|
|
1594
1625
|
}
|
|
@@ -2177,10 +2208,7 @@ function buildResponsesInput(request) {
|
|
|
2177
2208
|
return buildMessages(request);
|
|
2178
2209
|
}
|
|
2179
2210
|
function toOpenAIMessage(message) {
|
|
2180
|
-
return {
|
|
2181
|
-
role: message.role,
|
|
2182
|
-
content: message.content
|
|
2183
|
-
};
|
|
2211
|
+
return { ...message };
|
|
2184
2212
|
}
|
|
2185
2213
|
function toResponsesTools(tools) {
|
|
2186
2214
|
if (!Array.isArray(tools) || tools.length === 0) {
|
|
@@ -2648,6 +2676,9 @@ function createAnthropicCompatibleAdapter(options) {
|
|
|
2648
2676
|
const out = { text, usage, finishReason };
|
|
2649
2677
|
callbacks.onComplete?.(out);
|
|
2650
2678
|
return out;
|
|
2679
|
+
},
|
|
2680
|
+
async embed() {
|
|
2681
|
+
throw new Error("Anthropic does not provide a native embedding API. " + "Use the openai-compatible provider with Voyage AI (https://api.voyageai.com) — " + "Anthropic's recommended embedding solution, which uses the same request format.");
|
|
2651
2682
|
}
|
|
2652
2683
|
};
|
|
2653
2684
|
}
|
|
@@ -2926,6 +2957,23 @@ function toAnthropicInput(messages) {
|
|
|
2926
2957
|
continue;
|
|
2927
2958
|
}
|
|
2928
2959
|
sawNonSystem = true;
|
|
2960
|
+
if (message.role === "assistant" && Array.isArray(message.tool_calls)) {
|
|
2961
|
+
const parts = [];
|
|
2962
|
+
if (message.content)
|
|
2963
|
+
parts.push({ type: "text", text: message.content });
|
|
2964
|
+
for (const tc of message.tool_calls) {
|
|
2965
|
+
parts.push({ type: "tool_use", id: tc.id, name: tc.function.name, input: JSON.parse(tc.function.arguments) });
|
|
2966
|
+
}
|
|
2967
|
+
normalizedMessages.push({ role: "assistant", content: parts });
|
|
2968
|
+
continue;
|
|
2969
|
+
}
|
|
2970
|
+
if (message.role === "tool") {
|
|
2971
|
+
normalizedMessages.push({
|
|
2972
|
+
role: "user",
|
|
2973
|
+
content: [{ type: "tool_result", tool_use_id: message.tool_call_id, content: message.content }]
|
|
2974
|
+
});
|
|
2975
|
+
continue;
|
|
2976
|
+
}
|
|
2929
2977
|
normalizedMessages.push({
|
|
2930
2978
|
role: message.role,
|
|
2931
2979
|
content: message.content
|
|
@@ -4705,6 +4753,12 @@ function createLLM(config, registry = createDefaultProviderRegistry()) {
|
|
|
4705
4753
|
async structured(schema, prompt, options) {
|
|
4706
4754
|
const merged = mergeStructuredOptions(defaults, options);
|
|
4707
4755
|
return structured(adapter, schema, prompt, merged);
|
|
4756
|
+
},
|
|
4757
|
+
async embed(input, options = {}) {
|
|
4758
|
+
if (!adapter.embed) {
|
|
4759
|
+
throw new Error(`Provider "${adapter.provider ?? "unknown"}" does not support embeddings.`);
|
|
4760
|
+
}
|
|
4761
|
+
return adapter.embed({ ...options, input });
|
|
4708
4762
|
}
|
|
4709
4763
|
};
|
|
4710
4764
|
}
|
|
@@ -4870,10 +4924,32 @@ async function resizeImage(source, size, mimeType) {
|
|
|
4870
4924
|
function conversation(systemPrompt, entries) {
|
|
4871
4925
|
return [
|
|
4872
4926
|
{ role: "system", content: systemPrompt },
|
|
4873
|
-
...entries.map((entry) =>
|
|
4874
|
-
|
|
4875
|
-
|
|
4876
|
-
|
|
4927
|
+
...entries.map((entry) => {
|
|
4928
|
+
if (entry.role === "tool_call") {
|
|
4929
|
+
return {
|
|
4930
|
+
role: "assistant",
|
|
4931
|
+
content: "",
|
|
4932
|
+
tool_calls: [
|
|
4933
|
+
{
|
|
4934
|
+
id: entry.id,
|
|
4935
|
+
type: "function",
|
|
4936
|
+
function: { name: entry.name, arguments: JSON.stringify(entry.arguments ?? {}) }
|
|
4937
|
+
}
|
|
4938
|
+
]
|
|
4939
|
+
};
|
|
4940
|
+
}
|
|
4941
|
+
if (entry.role === "tool_result") {
|
|
4942
|
+
return {
|
|
4943
|
+
role: "tool",
|
|
4944
|
+
content: typeof entry.output === "string" ? entry.output : JSON.stringify(entry.output),
|
|
4945
|
+
tool_call_id: entry.id
|
|
4946
|
+
};
|
|
4947
|
+
}
|
|
4948
|
+
return {
|
|
4949
|
+
role: entry.role,
|
|
4950
|
+
content: entry.images && entry.images.length > 0 ? [{ type: "text", text: entry.text }, ...images(entry.images)] : entry.text
|
|
4951
|
+
};
|
|
4952
|
+
})
|
|
4877
4953
|
];
|
|
4878
4954
|
}
|
|
4879
4955
|
// src/prompt.ts
|
package/dist/llm.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { z } from "zod";
|
|
2
2
|
import { type ModelAdapterConfig, type ProviderRegistry } from "./providers/registry";
|
|
3
|
-
import type { LLMAdapter, StructuredCallOptions, StructuredPromptBuilder, StructuredResult } from "./types";
|
|
3
|
+
import type { EmbeddingRequest, EmbeddingResult, LLMAdapter, StructuredCallOptions, StructuredPromptBuilder, StructuredResult } from "./types";
|
|
4
4
|
export interface CreateLLMOptions extends ModelAdapterConfig {
|
|
5
5
|
defaults?: StructuredCallOptions<z.ZodTypeAny>;
|
|
6
6
|
}
|
|
@@ -9,5 +9,6 @@ export interface LLMClient {
|
|
|
9
9
|
provider?: string;
|
|
10
10
|
model?: string;
|
|
11
11
|
structured<TSchema extends z.ZodTypeAny>(schema: TSchema, prompt: StructuredPromptBuilder, options?: StructuredCallOptions<TSchema>): Promise<StructuredResult<z.infer<TSchema>>>;
|
|
12
|
+
embed(input: string | string[], options?: Omit<EmbeddingRequest, "input">): Promise<EmbeddingResult>;
|
|
12
13
|
}
|
|
13
14
|
export declare function createLLM(config: CreateLLMOptions, registry?: ProviderRegistry): LLMClient;
|
package/dist/types.d.ts
CHANGED
|
@@ -130,9 +130,18 @@ export interface LLMImageContent {
|
|
|
130
130
|
};
|
|
131
131
|
}
|
|
132
132
|
export type LLMMessageContent = string | (LLMTextContent | LLMImageContent)[];
|
|
133
|
+
export interface LLMToolCallRef {
|
|
134
|
+
id: string;
|
|
135
|
+
type: "function";
|
|
136
|
+
function: {
|
|
137
|
+
name: string;
|
|
138
|
+
arguments: string;
|
|
139
|
+
};
|
|
140
|
+
}
|
|
133
141
|
export interface LLMMessage {
|
|
134
142
|
role: "system" | "user" | "assistant" | "tool";
|
|
135
143
|
content: LLMMessageContent;
|
|
144
|
+
[key: string]: unknown;
|
|
136
145
|
}
|
|
137
146
|
export interface LLMRequest {
|
|
138
147
|
prompt?: string;
|
|
@@ -179,11 +188,24 @@ export interface LLMStreamCallbacks {
|
|
|
179
188
|
onChunk?: (chunk: LLMStreamChunk) => void;
|
|
180
189
|
onComplete?: (response: LLMResponse) => void;
|
|
181
190
|
}
|
|
191
|
+
export interface EmbeddingRequest {
|
|
192
|
+
input: string | string[];
|
|
193
|
+
model?: string;
|
|
194
|
+
dimensions?: number;
|
|
195
|
+
body?: Record<string, unknown>;
|
|
196
|
+
}
|
|
197
|
+
export interface EmbeddingResult {
|
|
198
|
+
embeddings: number[][];
|
|
199
|
+
model: string;
|
|
200
|
+
usage?: LLMUsage;
|
|
201
|
+
raw?: unknown;
|
|
202
|
+
}
|
|
182
203
|
export interface LLMAdapter {
|
|
183
204
|
provider?: string;
|
|
184
205
|
model?: string;
|
|
185
206
|
complete(request: LLMRequest): Promise<LLMResponse>;
|
|
186
207
|
stream?(request: LLMRequest, callbacks?: LLMStreamCallbacks): Promise<LLMResponse>;
|
|
208
|
+
embed?(request: EmbeddingRequest): Promise<EmbeddingResult>;
|
|
187
209
|
}
|
|
188
210
|
export interface LLMToolCall {
|
|
189
211
|
id: string;
|