extrait 0.3.1 → 0.4.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 +2 -0
- package/dist/index.cjs +32 -14
- package/dist/index.d.ts +1 -1
- package/dist/index.js +32 -14
- package/dist/types.d.ts +7 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -233,6 +233,7 @@ Run examples with: `bun run dev <example-name>`
|
|
|
233
233
|
Available examples:
|
|
234
234
|
- `streaming` - Real LLM streaming + snapshot self-check ([streaming.ts](examples/streaming.ts))
|
|
235
235
|
- `streaming-with-tools` - Real text streaming with MCP tools + self-check ([streaming-with-tools.ts](examples/streaming-with-tools.ts))
|
|
236
|
+
- `abort-signal` - Start a generation then cancel quickly with `AbortSignal` ([abort-signal.ts](examples/abort-signal.ts))
|
|
236
237
|
- `simple` - Basic structured output with streaming ([simple.ts](examples/simple.ts))
|
|
237
238
|
- `sentiment-analysis` - Enum validation, strict mode ([sentiment-analysis.ts](examples/sentiment-analysis.ts))
|
|
238
239
|
- `data-extraction` - Complex nested schemas, self-healing ([data-extraction.ts](examples/data-extraction.ts))
|
|
@@ -243,6 +244,7 @@ Pass arguments after the example name:
|
|
|
243
244
|
```bash
|
|
244
245
|
bun run dev streaming
|
|
245
246
|
bun run dev streaming-with-tools
|
|
247
|
+
bun run dev abort-signal 120 "JSON cancellation demo"
|
|
246
248
|
bun run dev simple "Bun.js runtime"
|
|
247
249
|
bun run dev sentiment-analysis "I love this product."
|
|
248
250
|
bun run dev multi-step-reasoning "Why is the sky blue?"
|
package/dist/index.cjs
CHANGED
|
@@ -1324,7 +1324,12 @@ async function executeMCPToolCalls(calls, toolset, context) {
|
|
|
1324
1324
|
out.push({ call: metadata2, execution });
|
|
1325
1325
|
continue;
|
|
1326
1326
|
}
|
|
1327
|
-
const
|
|
1327
|
+
const rawArgs = isRecord(parsedArguments) ? parsedArguments : {};
|
|
1328
|
+
const args = context.request.transformToolArguments ? await context.request.transformToolArguments(rawArgs, {
|
|
1329
|
+
name: toolName,
|
|
1330
|
+
remoteName: tool.remoteName,
|
|
1331
|
+
clientId: tool.clientId
|
|
1332
|
+
}) : rawArgs;
|
|
1328
1333
|
const metadata = {
|
|
1329
1334
|
id: callId,
|
|
1330
1335
|
type: call.type ?? "function",
|
|
@@ -1643,7 +1648,8 @@ function createOpenAICompatibleAdapter(options) {
|
|
|
1643
1648
|
temperature: request.temperature,
|
|
1644
1649
|
max_tokens: request.maxTokens,
|
|
1645
1650
|
stream: true
|
|
1646
|
-
}))
|
|
1651
|
+
})),
|
|
1652
|
+
signal: request.signal
|
|
1647
1653
|
});
|
|
1648
1654
|
if (!response.ok) {
|
|
1649
1655
|
const message = await response.text();
|
|
@@ -1714,7 +1720,8 @@ async function completeWithChatCompletionsPassThrough(options, fetcher, path, re
|
|
|
1714
1720
|
temperature: request.temperature,
|
|
1715
1721
|
max_tokens: request.maxTokens,
|
|
1716
1722
|
stream: false
|
|
1717
|
-
}))
|
|
1723
|
+
})),
|
|
1724
|
+
signal: request.signal
|
|
1718
1725
|
});
|
|
1719
1726
|
if (!response.ok) {
|
|
1720
1727
|
const message = await response.text();
|
|
@@ -1758,7 +1765,8 @@ async function completeWithChatCompletionsWithMCP(options, fetcher, path, reques
|
|
|
1758
1765
|
tools: transportTools,
|
|
1759
1766
|
tool_choice: request.toolChoice,
|
|
1760
1767
|
parallel_tool_calls: request.parallelToolCalls
|
|
1761
|
-
}))
|
|
1768
|
+
})),
|
|
1769
|
+
signal: request.signal
|
|
1762
1770
|
});
|
|
1763
1771
|
if (!response.ok) {
|
|
1764
1772
|
const message = await response.text();
|
|
@@ -1823,7 +1831,8 @@ async function completeWithResponsesAPIPassThrough(options, fetcher, path, reque
|
|
|
1823
1831
|
previous_response_id: pickString(body?.previous_response_id),
|
|
1824
1832
|
temperature: request.temperature,
|
|
1825
1833
|
max_output_tokens: request.maxTokens
|
|
1826
|
-
}))
|
|
1834
|
+
})),
|
|
1835
|
+
signal: request.signal
|
|
1827
1836
|
});
|
|
1828
1837
|
if (!response.ok) {
|
|
1829
1838
|
const message = await response.text();
|
|
@@ -1865,7 +1874,8 @@ async function completeWithResponsesAPIWithMCP(options, fetcher, path, request)
|
|
|
1865
1874
|
tools: transportTools,
|
|
1866
1875
|
tool_choice: request.toolChoice,
|
|
1867
1876
|
parallel_tool_calls: request.parallelToolCalls
|
|
1868
|
-
}))
|
|
1877
|
+
})),
|
|
1878
|
+
signal: request.signal
|
|
1869
1879
|
});
|
|
1870
1880
|
if (!response.ok) {
|
|
1871
1881
|
const message = await response.text();
|
|
@@ -1941,7 +1951,8 @@ async function streamWithChatCompletionsWithMCP(options, fetcher, path, request,
|
|
|
1941
1951
|
tool_choice: request.toolChoice,
|
|
1942
1952
|
parallel_tool_calls: request.parallelToolCalls,
|
|
1943
1953
|
stream: true
|
|
1944
|
-
}))
|
|
1954
|
+
})),
|
|
1955
|
+
signal: request.signal
|
|
1945
1956
|
});
|
|
1946
1957
|
if (!response.ok) {
|
|
1947
1958
|
const message = await response.text();
|
|
@@ -2043,7 +2054,8 @@ async function streamWithResponsesAPIPassThrough(options, fetcher, path, request
|
|
|
2043
2054
|
temperature: request.temperature,
|
|
2044
2055
|
max_output_tokens: request.maxTokens,
|
|
2045
2056
|
stream: true
|
|
2046
|
-
}))
|
|
2057
|
+
})),
|
|
2058
|
+
signal: request.signal
|
|
2047
2059
|
});
|
|
2048
2060
|
if (!response.ok) {
|
|
2049
2061
|
const message = await response.text();
|
|
@@ -2125,7 +2137,8 @@ async function streamWithResponsesAPIWithMCP(options, fetcher, path, request, ca
|
|
|
2125
2137
|
tool_choice: request.toolChoice,
|
|
2126
2138
|
parallel_tool_calls: request.parallelToolCalls,
|
|
2127
2139
|
stream: true
|
|
2128
|
-
}))
|
|
2140
|
+
})),
|
|
2141
|
+
signal: request.signal
|
|
2129
2142
|
});
|
|
2130
2143
|
if (!response.ok) {
|
|
2131
2144
|
const message = await response.text();
|
|
@@ -2689,7 +2702,8 @@ function createAnthropicCompatibleAdapter(options) {
|
|
|
2689
2702
|
temperature: request.temperature,
|
|
2690
2703
|
max_tokens: resolveMaxTokens(request.maxTokens, options.defaultMaxTokens),
|
|
2691
2704
|
stream: true
|
|
2692
|
-
}))
|
|
2705
|
+
})),
|
|
2706
|
+
signal: request.signal
|
|
2693
2707
|
});
|
|
2694
2708
|
if (!response.ok) {
|
|
2695
2709
|
const message = await response.text();
|
|
@@ -2747,7 +2761,8 @@ async function completePassThrough(options, fetcher, path, request) {
|
|
|
2747
2761
|
temperature: request.temperature,
|
|
2748
2762
|
max_tokens: resolveMaxTokens(request.maxTokens, options.defaultMaxTokens),
|
|
2749
2763
|
stream: false
|
|
2750
|
-
}))
|
|
2764
|
+
})),
|
|
2765
|
+
signal: request.signal
|
|
2751
2766
|
});
|
|
2752
2767
|
if (!response.ok) {
|
|
2753
2768
|
const message = await response.text();
|
|
@@ -2792,7 +2807,8 @@ async function completeWithMCPToolLoop(options, fetcher, path, request) {
|
|
|
2792
2807
|
tools,
|
|
2793
2808
|
tool_choice: toAnthropicToolChoice(request.toolChoice),
|
|
2794
2809
|
stream: false
|
|
2795
|
-
}))
|
|
2810
|
+
})),
|
|
2811
|
+
signal: request.signal
|
|
2796
2812
|
});
|
|
2797
2813
|
if (!response.ok) {
|
|
2798
2814
|
const message = await response.text();
|
|
@@ -2875,7 +2891,8 @@ async function streamWithMCPToolLoop(options, fetcher, path, request, callbacks)
|
|
|
2875
2891
|
tools,
|
|
2876
2892
|
tool_choice: toAnthropicToolChoice(request.toolChoice),
|
|
2877
2893
|
stream: true
|
|
2878
|
-
}))
|
|
2894
|
+
})),
|
|
2895
|
+
signal: request.signal
|
|
2879
2896
|
});
|
|
2880
2897
|
if (!response.ok) {
|
|
2881
2898
|
const message = await response.text();
|
|
@@ -4252,7 +4269,8 @@ async function callModel(adapter, options) {
|
|
|
4252
4269
|
maxToolRounds: options.request?.maxToolRounds,
|
|
4253
4270
|
onToolExecution: options.request?.onToolExecution,
|
|
4254
4271
|
toolDebug: options.request?.toolDebug,
|
|
4255
|
-
body: options.request?.body
|
|
4272
|
+
body: options.request?.body,
|
|
4273
|
+
signal: options.request?.signal
|
|
4256
4274
|
};
|
|
4257
4275
|
emitDebugRequest(options.debug, {
|
|
4258
4276
|
provider: adapter.provider,
|
package/dist/index.d.ts
CHANGED
|
@@ -12,4 +12,4 @@ export { createOpenAICompatibleAdapter, type OpenAICompatibleAdapterOptions, } f
|
|
|
12
12
|
export { createAnthropicCompatibleAdapter, DEFAULT_ANTHROPIC_MAX_TOKENS, DEFAULT_ANTHROPIC_VERSION, type AnthropicCompatibleAdapterOptions, } from "./providers/anthropic-compatible";
|
|
13
13
|
export { DEFAULT_MAX_TOOL_ROUNDS } from "./providers/mcp-runtime";
|
|
14
14
|
export { createDefaultProviderRegistry, createModelAdapter, createProviderRegistry, registerBuiltinProviders, type BuiltinProviderKind, type ModelAdapterConfig, type ProviderFactory, type ProviderRegistry, type ProviderTransportConfig, } from "./providers/registry";
|
|
15
|
-
export type { CandidateDiagnostics, ExtractJsonCandidatesOptions, ExtractionCandidate, ExtractionHeuristicsOptions, ExtractionParseHint, HTTPHeaders, LLMAdapter, LLMRequest, LLMResponse, LLMStreamCallbacks, LLMStreamChunk, LLMToolCall, LLMToolDebugOptions, LLMToolExecution, LLMToolOutputTransformer, 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, ThinkDiagnostics, ThinkBlock, StructuredTraceEvent, } from "./types";
|
|
15
|
+
export type { CandidateDiagnostics, ExtractJsonCandidatesOptions, ExtractionCandidate, ExtractionHeuristicsOptions, ExtractionParseHint, HTTPHeaders, LLMAdapter, 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, ThinkDiagnostics, ThinkBlock, StructuredTraceEvent, } from "./types";
|
package/dist/index.js
CHANGED
|
@@ -1245,7 +1245,12 @@ async function executeMCPToolCalls(calls, toolset, context) {
|
|
|
1245
1245
|
out.push({ call: metadata2, execution });
|
|
1246
1246
|
continue;
|
|
1247
1247
|
}
|
|
1248
|
-
const
|
|
1248
|
+
const rawArgs = isRecord(parsedArguments) ? parsedArguments : {};
|
|
1249
|
+
const args = context.request.transformToolArguments ? await context.request.transformToolArguments(rawArgs, {
|
|
1250
|
+
name: toolName,
|
|
1251
|
+
remoteName: tool.remoteName,
|
|
1252
|
+
clientId: tool.clientId
|
|
1253
|
+
}) : rawArgs;
|
|
1249
1254
|
const metadata = {
|
|
1250
1255
|
id: callId,
|
|
1251
1256
|
type: call.type ?? "function",
|
|
@@ -1564,7 +1569,8 @@ function createOpenAICompatibleAdapter(options) {
|
|
|
1564
1569
|
temperature: request.temperature,
|
|
1565
1570
|
max_tokens: request.maxTokens,
|
|
1566
1571
|
stream: true
|
|
1567
|
-
}))
|
|
1572
|
+
})),
|
|
1573
|
+
signal: request.signal
|
|
1568
1574
|
});
|
|
1569
1575
|
if (!response.ok) {
|
|
1570
1576
|
const message = await response.text();
|
|
@@ -1635,7 +1641,8 @@ async function completeWithChatCompletionsPassThrough(options, fetcher, path, re
|
|
|
1635
1641
|
temperature: request.temperature,
|
|
1636
1642
|
max_tokens: request.maxTokens,
|
|
1637
1643
|
stream: false
|
|
1638
|
-
}))
|
|
1644
|
+
})),
|
|
1645
|
+
signal: request.signal
|
|
1639
1646
|
});
|
|
1640
1647
|
if (!response.ok) {
|
|
1641
1648
|
const message = await response.text();
|
|
@@ -1679,7 +1686,8 @@ async function completeWithChatCompletionsWithMCP(options, fetcher, path, reques
|
|
|
1679
1686
|
tools: transportTools,
|
|
1680
1687
|
tool_choice: request.toolChoice,
|
|
1681
1688
|
parallel_tool_calls: request.parallelToolCalls
|
|
1682
|
-
}))
|
|
1689
|
+
})),
|
|
1690
|
+
signal: request.signal
|
|
1683
1691
|
});
|
|
1684
1692
|
if (!response.ok) {
|
|
1685
1693
|
const message = await response.text();
|
|
@@ -1744,7 +1752,8 @@ async function completeWithResponsesAPIPassThrough(options, fetcher, path, reque
|
|
|
1744
1752
|
previous_response_id: pickString(body?.previous_response_id),
|
|
1745
1753
|
temperature: request.temperature,
|
|
1746
1754
|
max_output_tokens: request.maxTokens
|
|
1747
|
-
}))
|
|
1755
|
+
})),
|
|
1756
|
+
signal: request.signal
|
|
1748
1757
|
});
|
|
1749
1758
|
if (!response.ok) {
|
|
1750
1759
|
const message = await response.text();
|
|
@@ -1786,7 +1795,8 @@ async function completeWithResponsesAPIWithMCP(options, fetcher, path, request)
|
|
|
1786
1795
|
tools: transportTools,
|
|
1787
1796
|
tool_choice: request.toolChoice,
|
|
1788
1797
|
parallel_tool_calls: request.parallelToolCalls
|
|
1789
|
-
}))
|
|
1798
|
+
})),
|
|
1799
|
+
signal: request.signal
|
|
1790
1800
|
});
|
|
1791
1801
|
if (!response.ok) {
|
|
1792
1802
|
const message = await response.text();
|
|
@@ -1862,7 +1872,8 @@ async function streamWithChatCompletionsWithMCP(options, fetcher, path, request,
|
|
|
1862
1872
|
tool_choice: request.toolChoice,
|
|
1863
1873
|
parallel_tool_calls: request.parallelToolCalls,
|
|
1864
1874
|
stream: true
|
|
1865
|
-
}))
|
|
1875
|
+
})),
|
|
1876
|
+
signal: request.signal
|
|
1866
1877
|
});
|
|
1867
1878
|
if (!response.ok) {
|
|
1868
1879
|
const message = await response.text();
|
|
@@ -1964,7 +1975,8 @@ async function streamWithResponsesAPIPassThrough(options, fetcher, path, request
|
|
|
1964
1975
|
temperature: request.temperature,
|
|
1965
1976
|
max_output_tokens: request.maxTokens,
|
|
1966
1977
|
stream: true
|
|
1967
|
-
}))
|
|
1978
|
+
})),
|
|
1979
|
+
signal: request.signal
|
|
1968
1980
|
});
|
|
1969
1981
|
if (!response.ok) {
|
|
1970
1982
|
const message = await response.text();
|
|
@@ -2046,7 +2058,8 @@ async function streamWithResponsesAPIWithMCP(options, fetcher, path, request, ca
|
|
|
2046
2058
|
tool_choice: request.toolChoice,
|
|
2047
2059
|
parallel_tool_calls: request.parallelToolCalls,
|
|
2048
2060
|
stream: true
|
|
2049
|
-
}))
|
|
2061
|
+
})),
|
|
2062
|
+
signal: request.signal
|
|
2050
2063
|
});
|
|
2051
2064
|
if (!response.ok) {
|
|
2052
2065
|
const message = await response.text();
|
|
@@ -2610,7 +2623,8 @@ function createAnthropicCompatibleAdapter(options) {
|
|
|
2610
2623
|
temperature: request.temperature,
|
|
2611
2624
|
max_tokens: resolveMaxTokens(request.maxTokens, options.defaultMaxTokens),
|
|
2612
2625
|
stream: true
|
|
2613
|
-
}))
|
|
2626
|
+
})),
|
|
2627
|
+
signal: request.signal
|
|
2614
2628
|
});
|
|
2615
2629
|
if (!response.ok) {
|
|
2616
2630
|
const message = await response.text();
|
|
@@ -2668,7 +2682,8 @@ async function completePassThrough(options, fetcher, path, request) {
|
|
|
2668
2682
|
temperature: request.temperature,
|
|
2669
2683
|
max_tokens: resolveMaxTokens(request.maxTokens, options.defaultMaxTokens),
|
|
2670
2684
|
stream: false
|
|
2671
|
-
}))
|
|
2685
|
+
})),
|
|
2686
|
+
signal: request.signal
|
|
2672
2687
|
});
|
|
2673
2688
|
if (!response.ok) {
|
|
2674
2689
|
const message = await response.text();
|
|
@@ -2713,7 +2728,8 @@ async function completeWithMCPToolLoop(options, fetcher, path, request) {
|
|
|
2713
2728
|
tools,
|
|
2714
2729
|
tool_choice: toAnthropicToolChoice(request.toolChoice),
|
|
2715
2730
|
stream: false
|
|
2716
|
-
}))
|
|
2731
|
+
})),
|
|
2732
|
+
signal: request.signal
|
|
2717
2733
|
});
|
|
2718
2734
|
if (!response.ok) {
|
|
2719
2735
|
const message = await response.text();
|
|
@@ -2796,7 +2812,8 @@ async function streamWithMCPToolLoop(options, fetcher, path, request, callbacks)
|
|
|
2796
2812
|
tools,
|
|
2797
2813
|
tool_choice: toAnthropicToolChoice(request.toolChoice),
|
|
2798
2814
|
stream: true
|
|
2799
|
-
}))
|
|
2815
|
+
})),
|
|
2816
|
+
signal: request.signal
|
|
2800
2817
|
});
|
|
2801
2818
|
if (!response.ok) {
|
|
2802
2819
|
const message = await response.text();
|
|
@@ -4173,7 +4190,8 @@ async function callModel(adapter, options) {
|
|
|
4173
4190
|
maxToolRounds: options.request?.maxToolRounds,
|
|
4174
4191
|
onToolExecution: options.request?.onToolExecution,
|
|
4175
4192
|
toolDebug: options.request?.toolDebug,
|
|
4176
|
-
body: options.request?.body
|
|
4193
|
+
body: options.request?.body,
|
|
4194
|
+
signal: options.request?.signal
|
|
4177
4195
|
};
|
|
4178
4196
|
emitDebugRequest(options.debug, {
|
|
4179
4197
|
provider: adapter.provider,
|
package/dist/types.d.ts
CHANGED
|
@@ -130,9 +130,11 @@ export interface LLMRequest {
|
|
|
130
130
|
maxToolRounds?: number;
|
|
131
131
|
onToolExecution?: (execution: LLMToolExecution) => void;
|
|
132
132
|
transformToolOutput?: LLMToolOutputTransformer;
|
|
133
|
+
transformToolArguments?: LLMToolArgumentsTransformer;
|
|
133
134
|
unknownToolError?: (toolName: string) => string;
|
|
134
135
|
toolDebug?: boolean | LLMToolDebugOptions;
|
|
135
136
|
body?: Record<string, unknown>;
|
|
137
|
+
signal?: AbortSignal;
|
|
136
138
|
}
|
|
137
139
|
export interface LLMUsage {
|
|
138
140
|
inputTokens?: number;
|
|
@@ -192,6 +194,11 @@ export interface LLMToolExecution {
|
|
|
192
194
|
durationMs?: number;
|
|
193
195
|
}
|
|
194
196
|
export type LLMToolOutputTransformer = (output: unknown, execution: Omit<LLMToolExecution, "output" | "durationMs">) => unknown | Promise<unknown>;
|
|
197
|
+
export type LLMToolArgumentsTransformer = (args: Record<string, unknown>, context: {
|
|
198
|
+
name: string;
|
|
199
|
+
remoteName: string;
|
|
200
|
+
clientId: string;
|
|
201
|
+
}) => Record<string, unknown> | Promise<Record<string, unknown>>;
|
|
195
202
|
export interface LLMToolDebugOptions {
|
|
196
203
|
enabled?: boolean;
|
|
197
204
|
logger?: (line: string) => void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "extrait",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -36,10 +36,10 @@
|
|
|
36
36
|
"prepublishOnly": "bun run lint && bun run build && bun run build:types",
|
|
37
37
|
"test": "bun test tests/ --reporter=dots --only-failures",
|
|
38
38
|
"typecheck": "bunx tsc --noEmit",
|
|
39
|
-
"pack": "bun run build && npm pack"
|
|
39
|
+
"pack": "bun run build:types && bun run build && npm pack"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
42
|
+
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
43
43
|
"jsonrepair": "^3.13.2",
|
|
44
44
|
"zod": "^3.25.76"
|
|
45
45
|
},
|