extrait 0.6.0 → 0.6.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.
- package/dist/index.cjs +59 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +59 -2
- package/dist/types.d.ts +2 -1
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -1553,7 +1553,15 @@ function normalizeBaseURL(baseURL) {
|
|
|
1553
1553
|
return baseURL.endsWith("/") ? baseURL : `${baseURL}/`;
|
|
1554
1554
|
}
|
|
1555
1555
|
function buildURL(baseURL, path) {
|
|
1556
|
-
|
|
1556
|
+
try {
|
|
1557
|
+
return new URL(path).toString();
|
|
1558
|
+
} catch {}
|
|
1559
|
+
const base = new URL(normalizeBaseURL(baseURL));
|
|
1560
|
+
const resolvedPath = new URL(path, "http://provider-path.local");
|
|
1561
|
+
base.pathname = mergePathnames(base.pathname, resolvedPath.pathname);
|
|
1562
|
+
base.search = resolvedPath.search;
|
|
1563
|
+
base.hash = resolvedPath.hash;
|
|
1564
|
+
return base.toString();
|
|
1557
1565
|
}
|
|
1558
1566
|
function safeJSONParse(input) {
|
|
1559
1567
|
try {
|
|
@@ -1628,6 +1636,36 @@ function addOptional(a, b) {
|
|
|
1628
1636
|
}
|
|
1629
1637
|
return (a ?? 0) + (b ?? 0);
|
|
1630
1638
|
}
|
|
1639
|
+
function mergePathnames(basePathname, pathPathname) {
|
|
1640
|
+
const baseSegments = splitPathSegments(basePathname);
|
|
1641
|
+
const pathSegments = splitPathSegments(pathPathname);
|
|
1642
|
+
const overlap = findPathOverlap(baseSegments, pathSegments);
|
|
1643
|
+
const mergedSegments = [...baseSegments, ...pathSegments.slice(overlap)];
|
|
1644
|
+
if (mergedSegments.length === 0) {
|
|
1645
|
+
return "/";
|
|
1646
|
+
}
|
|
1647
|
+
const mergedPathname = `/${mergedSegments.join("/")}`;
|
|
1648
|
+
return pathPathname.endsWith("/") && pathPathname !== "/" ? `${mergedPathname}/` : mergedPathname;
|
|
1649
|
+
}
|
|
1650
|
+
function splitPathSegments(pathname) {
|
|
1651
|
+
return pathname.split("/").filter((segment) => segment.length > 0);
|
|
1652
|
+
}
|
|
1653
|
+
function findPathOverlap(baseSegments, pathSegments) {
|
|
1654
|
+
const maxOverlap = Math.min(baseSegments.length, pathSegments.length);
|
|
1655
|
+
for (let size = maxOverlap;size > 0; size -= 1) {
|
|
1656
|
+
let matches = true;
|
|
1657
|
+
for (let index = 0;index < size; index += 1) {
|
|
1658
|
+
if (baseSegments[baseSegments.length - size + index] !== pathSegments[index]) {
|
|
1659
|
+
matches = false;
|
|
1660
|
+
break;
|
|
1661
|
+
}
|
|
1662
|
+
}
|
|
1663
|
+
if (matches) {
|
|
1664
|
+
return size;
|
|
1665
|
+
}
|
|
1666
|
+
}
|
|
1667
|
+
return 0;
|
|
1668
|
+
}
|
|
1631
1669
|
|
|
1632
1670
|
// src/providers/openai-compatible.ts
|
|
1633
1671
|
function createOpenAICompatibleAdapter(options) {
|
|
@@ -1786,7 +1824,7 @@ async function completeWithChatCompletionsPassThrough(options, fetcher, path, re
|
|
|
1786
1824
|
const message = await response.text();
|
|
1787
1825
|
throw new Error(`HTTP ${response.status}: ${message}`);
|
|
1788
1826
|
}
|
|
1789
|
-
const payload = await response
|
|
1827
|
+
const payload = await parseOpenAICompatibleJSONResponse(response, "Failed to parse OpenAI-compatible chat completion response");
|
|
1790
1828
|
const assistantMessage = pickAssistantMessage(payload);
|
|
1791
1829
|
if (!assistantMessage) {
|
|
1792
1830
|
throw new Error("No assistant message in OpenAI-compatible response.");
|
|
@@ -1802,6 +1840,25 @@ async function completeWithChatCompletionsPassThrough(options, fetcher, path, re
|
|
|
1802
1840
|
toolCalls: toolCalls.length > 0 ? toolCalls : undefined
|
|
1803
1841
|
};
|
|
1804
1842
|
}
|
|
1843
|
+
async function parseOpenAICompatibleJSONResponse(response, context) {
|
|
1844
|
+
const rawBody = await response.text();
|
|
1845
|
+
try {
|
|
1846
|
+
return JSON.parse(rawBody);
|
|
1847
|
+
} catch (error) {
|
|
1848
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1849
|
+
throw new Error(`${context} (HTTP ${response.status}): ${message}. Raw body: ${formatResponseBodyForError(rawBody)}`);
|
|
1850
|
+
}
|
|
1851
|
+
}
|
|
1852
|
+
function formatResponseBodyForError(rawBody, maxLength = 2000) {
|
|
1853
|
+
const normalized = rawBody.trim();
|
|
1854
|
+
if (normalized.length === 0) {
|
|
1855
|
+
return "[empty body]";
|
|
1856
|
+
}
|
|
1857
|
+
if (normalized.length <= maxLength) {
|
|
1858
|
+
return normalized;
|
|
1859
|
+
}
|
|
1860
|
+
return `${normalized.slice(0, maxLength)}...[truncated ${normalized.length - maxLength} chars]`;
|
|
1861
|
+
}
|
|
1805
1862
|
async function completeWithChatCompletionsWithMCP(options, fetcher, path, request) {
|
|
1806
1863
|
const maxToolRounds = normalizeMaxToolRounds(request.maxToolRounds ?? options.defaultMaxToolRounds);
|
|
1807
1864
|
let messages = buildMessages(request);
|
package/dist/index.d.ts
CHANGED
|
@@ -15,4 +15,4 @@ export { createOpenAICompatibleAdapter, type OpenAICompatibleAdapterOptions, } f
|
|
|
15
15
|
export { createAnthropicCompatibleAdapter, DEFAULT_ANTHROPIC_MAX_TOKENS, DEFAULT_ANTHROPIC_VERSION, type AnthropicCompatibleAdapterOptions, } from "./providers/anthropic-compatible";
|
|
16
16
|
export { DEFAULT_MAX_TOOL_ROUNDS } from "./providers/mcp-runtime";
|
|
17
17
|
export { createDefaultProviderRegistry, createModelAdapter, createProviderRegistry, registerBuiltinProviders, type BuiltinProviderKind, type ModelAdapterConfig, type ProviderFactory, type ProviderRegistry, type ProviderTransportConfig, } from "./providers/registry";
|
|
18
|
-
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, LLMToolCallParamsTransformer, 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, StructuredStreamDelta, StructuredStreamEvent, StructuredStreamInput, StructuredStreamOptions, StructuredStreamSnapshot, StructuredSelfHealInput, StructuredTimeoutOptions, ThinkDiagnostics, ThinkBlock, StructuredTraceEvent, GenerateAttempt, GenerateCallOptions, GenerateOptions, GenerateResult, GenerateStreamDelta, GenerateStreamEvent, GenerateStreamInput, GenerateStreamOptions, GenerateStreamSnapshot, GenerateTraceEvent, } from "./types";
|
|
18
|
+
export type { CandidateDiagnostics, EmbeddingRequest, EmbeddingResult, LLMImageContent, LLMMessageContent, LLMReasoningEffort, LLMTextContent, ExtractJsonCandidatesOptions, ExtractionCandidate, ExtractionHeuristicsOptions, ExtractionParseHint, HTTPHeaders, LLMAdapter, LLMMessage, LLMRequest, LLMResponse, LLMStreamCallbacks, LLMStreamChunk, LLMToolCall, LLMToolCallRef, LLMToolDebugOptions, LLMToolExecution, LLMToolOutputTransformer, LLMToolArgumentsTransformer, LLMToolCallParamsTransformer, 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, StructuredStreamDelta, StructuredStreamEvent, StructuredStreamInput, StructuredStreamOptions, StructuredStreamSnapshot, StructuredSelfHealInput, StructuredTimeoutOptions, ThinkDiagnostics, ThinkBlock, StructuredTraceEvent, GenerateAttempt, GenerateCallOptions, GenerateOptions, GenerateResult, GenerateStreamDelta, GenerateStreamEvent, GenerateStreamInput, GenerateStreamOptions, GenerateStreamSnapshot, GenerateTraceEvent, } from "./types";
|
package/dist/index.js
CHANGED
|
@@ -1463,7 +1463,15 @@ function normalizeBaseURL(baseURL) {
|
|
|
1463
1463
|
return baseURL.endsWith("/") ? baseURL : `${baseURL}/`;
|
|
1464
1464
|
}
|
|
1465
1465
|
function buildURL(baseURL, path) {
|
|
1466
|
-
|
|
1466
|
+
try {
|
|
1467
|
+
return new URL(path).toString();
|
|
1468
|
+
} catch {}
|
|
1469
|
+
const base = new URL(normalizeBaseURL(baseURL));
|
|
1470
|
+
const resolvedPath = new URL(path, "http://provider-path.local");
|
|
1471
|
+
base.pathname = mergePathnames(base.pathname, resolvedPath.pathname);
|
|
1472
|
+
base.search = resolvedPath.search;
|
|
1473
|
+
base.hash = resolvedPath.hash;
|
|
1474
|
+
return base.toString();
|
|
1467
1475
|
}
|
|
1468
1476
|
function safeJSONParse(input) {
|
|
1469
1477
|
try {
|
|
@@ -1538,6 +1546,36 @@ function addOptional(a, b) {
|
|
|
1538
1546
|
}
|
|
1539
1547
|
return (a ?? 0) + (b ?? 0);
|
|
1540
1548
|
}
|
|
1549
|
+
function mergePathnames(basePathname, pathPathname) {
|
|
1550
|
+
const baseSegments = splitPathSegments(basePathname);
|
|
1551
|
+
const pathSegments = splitPathSegments(pathPathname);
|
|
1552
|
+
const overlap = findPathOverlap(baseSegments, pathSegments);
|
|
1553
|
+
const mergedSegments = [...baseSegments, ...pathSegments.slice(overlap)];
|
|
1554
|
+
if (mergedSegments.length === 0) {
|
|
1555
|
+
return "/";
|
|
1556
|
+
}
|
|
1557
|
+
const mergedPathname = `/${mergedSegments.join("/")}`;
|
|
1558
|
+
return pathPathname.endsWith("/") && pathPathname !== "/" ? `${mergedPathname}/` : mergedPathname;
|
|
1559
|
+
}
|
|
1560
|
+
function splitPathSegments(pathname) {
|
|
1561
|
+
return pathname.split("/").filter((segment) => segment.length > 0);
|
|
1562
|
+
}
|
|
1563
|
+
function findPathOverlap(baseSegments, pathSegments) {
|
|
1564
|
+
const maxOverlap = Math.min(baseSegments.length, pathSegments.length);
|
|
1565
|
+
for (let size = maxOverlap;size > 0; size -= 1) {
|
|
1566
|
+
let matches = true;
|
|
1567
|
+
for (let index = 0;index < size; index += 1) {
|
|
1568
|
+
if (baseSegments[baseSegments.length - size + index] !== pathSegments[index]) {
|
|
1569
|
+
matches = false;
|
|
1570
|
+
break;
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
if (matches) {
|
|
1574
|
+
return size;
|
|
1575
|
+
}
|
|
1576
|
+
}
|
|
1577
|
+
return 0;
|
|
1578
|
+
}
|
|
1541
1579
|
|
|
1542
1580
|
// src/providers/openai-compatible.ts
|
|
1543
1581
|
function createOpenAICompatibleAdapter(options) {
|
|
@@ -1696,7 +1734,7 @@ async function completeWithChatCompletionsPassThrough(options, fetcher, path, re
|
|
|
1696
1734
|
const message = await response.text();
|
|
1697
1735
|
throw new Error(`HTTP ${response.status}: ${message}`);
|
|
1698
1736
|
}
|
|
1699
|
-
const payload = await response
|
|
1737
|
+
const payload = await parseOpenAICompatibleJSONResponse(response, "Failed to parse OpenAI-compatible chat completion response");
|
|
1700
1738
|
const assistantMessage = pickAssistantMessage(payload);
|
|
1701
1739
|
if (!assistantMessage) {
|
|
1702
1740
|
throw new Error("No assistant message in OpenAI-compatible response.");
|
|
@@ -1712,6 +1750,25 @@ async function completeWithChatCompletionsPassThrough(options, fetcher, path, re
|
|
|
1712
1750
|
toolCalls: toolCalls.length > 0 ? toolCalls : undefined
|
|
1713
1751
|
};
|
|
1714
1752
|
}
|
|
1753
|
+
async function parseOpenAICompatibleJSONResponse(response, context) {
|
|
1754
|
+
const rawBody = await response.text();
|
|
1755
|
+
try {
|
|
1756
|
+
return JSON.parse(rawBody);
|
|
1757
|
+
} catch (error) {
|
|
1758
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1759
|
+
throw new Error(`${context} (HTTP ${response.status}): ${message}. Raw body: ${formatResponseBodyForError(rawBody)}`);
|
|
1760
|
+
}
|
|
1761
|
+
}
|
|
1762
|
+
function formatResponseBodyForError(rawBody, maxLength = 2000) {
|
|
1763
|
+
const normalized = rawBody.trim();
|
|
1764
|
+
if (normalized.length === 0) {
|
|
1765
|
+
return "[empty body]";
|
|
1766
|
+
}
|
|
1767
|
+
if (normalized.length <= maxLength) {
|
|
1768
|
+
return normalized;
|
|
1769
|
+
}
|
|
1770
|
+
return `${normalized.slice(0, maxLength)}...[truncated ${normalized.length - maxLength} chars]`;
|
|
1771
|
+
}
|
|
1715
1772
|
async function completeWithChatCompletionsWithMCP(options, fetcher, path, request) {
|
|
1716
1773
|
const maxToolRounds = normalizeMaxToolRounds(request.maxToolRounds ?? options.defaultMaxToolRounds);
|
|
1717
1774
|
let messages = buildMessages(request);
|
package/dist/types.d.ts
CHANGED
|
@@ -144,12 +144,13 @@ export interface LLMMessage {
|
|
|
144
144
|
content: LLMMessageContent;
|
|
145
145
|
[key: string]: unknown;
|
|
146
146
|
}
|
|
147
|
+
export type LLMReasoningEffort = "none" | "minimal" | "low" | "medium" | "high" | "max";
|
|
147
148
|
export interface LLMRequest {
|
|
148
149
|
prompt?: string;
|
|
149
150
|
systemPrompt?: string;
|
|
150
151
|
messages?: LLMMessage[];
|
|
151
152
|
temperature?: number;
|
|
152
|
-
reasoningEffort?:
|
|
153
|
+
reasoningEffort?: LLMReasoningEffort;
|
|
153
154
|
maxTokens?: number;
|
|
154
155
|
mcpClients?: MCPToolClient[];
|
|
155
156
|
toolChoice?: LLMToolChoice;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "extrait",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/tterrasson/extrait.git"
|
|
@@ -8,12 +8,12 @@
|
|
|
8
8
|
"main": "./dist/index.cjs",
|
|
9
9
|
"module": "./dist/index.js",
|
|
10
10
|
"dependencies": {
|
|
11
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
12
|
-
"jsonrepair": "^3.13.
|
|
11
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
12
|
+
"jsonrepair": "^3.13.3",
|
|
13
13
|
"zod": "^4.3.6"
|
|
14
14
|
},
|
|
15
15
|
"devDependencies": {
|
|
16
|
-
"@types/bun": "^1.3.
|
|
16
|
+
"@types/bun": "^1.3.11",
|
|
17
17
|
"@types/sharp": "^0.32.0",
|
|
18
18
|
"typescript": "^5.9.3"
|
|
19
19
|
},
|