@animalabs/membrane 0.5.44 → 0.5.46
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/formatters/index.d.ts +0 -1
- package/dist/formatters/index.js +0 -1
- package/dist/formatters/index.js.map +1 -1
- package/dist/formatters/types.d.ts +0 -4
- package/dist/providers/bedrock.d.ts.map +1 -1
- package/dist/providers/bedrock.js +44 -7
- package/dist/providers/bedrock.js.map +1 -1
- package/dist/providers/gemini.js +11 -2
- package/dist/providers/gemini.js.map +1 -1
- package/dist/providers/openai-compatible.js +25 -15
- package/dist/providers/openai-compatible.js.map +1 -1
- package/dist/providers/openai-completions.js +48 -24
- package/dist/providers/openai-completions.js.map +1 -1
- package/dist/providers/openai-responses.js +6 -1
- package/dist/providers/openai-responses.js.map +1 -1
- package/dist/providers/openai.js +25 -15
- package/dist/providers/openai.js.map +1 -1
- package/dist/providers/openrouter.js +35 -16
- package/dist/providers/openrouter.js.map +1 -1
- package/dist/providers/utils.d.ts +38 -0
- package/dist/providers/utils.d.ts.map +1 -1
- package/dist/providers/utils.js +86 -0
- package/dist/providers/utils.js.map +1 -1
- package/dist/types/request.d.ts +8 -0
- package/dist/types/request.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/providers/bedrock.ts +40 -3
- package/dist/formatters/pseudo-prefill.d.ts +0 -71
- package/dist/formatters/pseudo-prefill.d.ts.map +0 -1
- package/dist/formatters/pseudo-prefill.js +0 -410
- package/dist/formatters/pseudo-prefill.js.map +0 -1
- package/dist/transforms/prefill.d.ts +0 -89
- package/dist/transforms/prefill.d.ts.map +0 -1
- package/dist/transforms/prefill.js +0 -390
- package/dist/transforms/prefill.js.map +0 -1
|
@@ -3,4 +3,42 @@
|
|
|
3
3
|
* Used for tool call arguments which may be malformed from streaming.
|
|
4
4
|
*/
|
|
5
5
|
export declare function safeParseJson(str: string | undefined): Record<string, unknown>;
|
|
6
|
+
/**
|
|
7
|
+
* Create a combined AbortSignal that fires on either the caller's signal
|
|
8
|
+
* or a timeout (whichever comes first).
|
|
9
|
+
*
|
|
10
|
+
* The returned `cleanup` function MUST be called in a `finally` block to
|
|
11
|
+
* clear the timeout and remove the event listener, preventing leaks.
|
|
12
|
+
*
|
|
13
|
+
* Timeout aborts with `DOMException('Request timed out', 'AbortError')`
|
|
14
|
+
* so it classifies identically to user-initiated aborts.
|
|
15
|
+
*/
|
|
16
|
+
export declare function createCombinedSignal(signal?: AbortSignal, timeoutMs?: number): {
|
|
17
|
+
signal?: AbortSignal;
|
|
18
|
+
cleanup?: () => void;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* SSE (Server-Sent Events) line parser that correctly handles events
|
|
22
|
+
* split across multiple TCP chunks.
|
|
23
|
+
*
|
|
24
|
+
* The naive approach of `chunk.split('\n').filter(l => l.startsWith('data: '))`
|
|
25
|
+
* silently drops events when an SSE line spans two chunks:
|
|
26
|
+
* Chunk 1: `data: {"choices":[{"delta":{"content":"don'` (no newline — incomplete)
|
|
27
|
+
* Chunk 2: `t do that"}}]}\n` (doesn't start with `data: `)
|
|
28
|
+
* Result: the entire event is lost, causing "skipped words" in output.
|
|
29
|
+
*
|
|
30
|
+
* This parser buffers partial lines and only yields complete `data: ...` lines.
|
|
31
|
+
*/
|
|
32
|
+
export declare class SSELineParser {
|
|
33
|
+
private buffer;
|
|
34
|
+
/**
|
|
35
|
+
* Feed a raw chunk from the stream reader and get back complete SSE data lines.
|
|
36
|
+
* Each returned string is the content after `data: ` (e.g. the JSON payload or `[DONE]`).
|
|
37
|
+
*/
|
|
38
|
+
feed(chunk: string): string[];
|
|
39
|
+
/**
|
|
40
|
+
* Flush any remaining buffered content (call when stream ends).
|
|
41
|
+
*/
|
|
42
|
+
flush(): string[];
|
|
43
|
+
}
|
|
6
44
|
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/providers/utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAO9E"}
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/providers/utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAO9E;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,CAAC,EAAE,WAAW,EACpB,SAAS,CAAC,EAAE,MAAM,GACjB;IAAE,MAAM,CAAC,EAAE,WAAW,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;CAAE,CA8BhD;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAc;IAE5B;;;OAGG;IACH,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IAmB7B;;OAEG;IACH,KAAK,IAAI,MAAM,EAAE;CASlB"}
|
package/dist/providers/utils.js
CHANGED
|
@@ -11,4 +11,90 @@ export function safeParseJson(str) {
|
|
|
11
11
|
return {};
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Create a combined AbortSignal that fires on either the caller's signal
|
|
16
|
+
* or a timeout (whichever comes first).
|
|
17
|
+
*
|
|
18
|
+
* The returned `cleanup` function MUST be called in a `finally` block to
|
|
19
|
+
* clear the timeout and remove the event listener, preventing leaks.
|
|
20
|
+
*
|
|
21
|
+
* Timeout aborts with `DOMException('Request timed out', 'AbortError')`
|
|
22
|
+
* so it classifies identically to user-initiated aborts.
|
|
23
|
+
*/
|
|
24
|
+
export function createCombinedSignal(signal, timeoutMs) {
|
|
25
|
+
if (!signal && !timeoutMs)
|
|
26
|
+
return {};
|
|
27
|
+
if (signal && !timeoutMs)
|
|
28
|
+
return { signal };
|
|
29
|
+
const controller = new AbortController();
|
|
30
|
+
let timeoutId;
|
|
31
|
+
if (timeoutMs) {
|
|
32
|
+
timeoutId = setTimeout(() => controller.abort(new DOMException('Request timed out', 'AbortError')), timeoutMs);
|
|
33
|
+
}
|
|
34
|
+
const onAbort = () => controller.abort(signal.reason);
|
|
35
|
+
if (signal) {
|
|
36
|
+
if (signal.aborted) {
|
|
37
|
+
controller.abort(signal.reason);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return {
|
|
44
|
+
signal: controller.signal,
|
|
45
|
+
cleanup: () => {
|
|
46
|
+
if (timeoutId)
|
|
47
|
+
clearTimeout(timeoutId);
|
|
48
|
+
if (signal)
|
|
49
|
+
signal.removeEventListener('abort', onAbort);
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* SSE (Server-Sent Events) line parser that correctly handles events
|
|
55
|
+
* split across multiple TCP chunks.
|
|
56
|
+
*
|
|
57
|
+
* The naive approach of `chunk.split('\n').filter(l => l.startsWith('data: '))`
|
|
58
|
+
* silently drops events when an SSE line spans two chunks:
|
|
59
|
+
* Chunk 1: `data: {"choices":[{"delta":{"content":"don'` (no newline — incomplete)
|
|
60
|
+
* Chunk 2: `t do that"}}]}\n` (doesn't start with `data: `)
|
|
61
|
+
* Result: the entire event is lost, causing "skipped words" in output.
|
|
62
|
+
*
|
|
63
|
+
* This parser buffers partial lines and only yields complete `data: ...` lines.
|
|
64
|
+
*/
|
|
65
|
+
export class SSELineParser {
|
|
66
|
+
buffer = '';
|
|
67
|
+
/**
|
|
68
|
+
* Feed a raw chunk from the stream reader and get back complete SSE data lines.
|
|
69
|
+
* Each returned string is the content after `data: ` (e.g. the JSON payload or `[DONE]`).
|
|
70
|
+
*/
|
|
71
|
+
feed(chunk) {
|
|
72
|
+
this.buffer += chunk;
|
|
73
|
+
const results = [];
|
|
74
|
+
// Split on newlines, keeping the last (potentially incomplete) segment in the buffer
|
|
75
|
+
const lines = this.buffer.split('\n');
|
|
76
|
+
this.buffer = lines.pop() || '';
|
|
77
|
+
for (const line of lines) {
|
|
78
|
+
const trimmed = line.trim();
|
|
79
|
+
if (trimmed.startsWith('data: ')) {
|
|
80
|
+
results.push(trimmed.slice(6));
|
|
81
|
+
}
|
|
82
|
+
// Skip empty lines, comments (`:...`), and other SSE fields (event:, id:, retry:)
|
|
83
|
+
}
|
|
84
|
+
return results;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Flush any remaining buffered content (call when stream ends).
|
|
88
|
+
*/
|
|
89
|
+
flush() {
|
|
90
|
+
if (!this.buffer.trim())
|
|
91
|
+
return [];
|
|
92
|
+
const trimmed = this.buffer.trim();
|
|
93
|
+
this.buffer = '';
|
|
94
|
+
if (trimmed.startsWith('data: ')) {
|
|
95
|
+
return [trimmed.slice(6)];
|
|
96
|
+
}
|
|
97
|
+
return [];
|
|
98
|
+
}
|
|
99
|
+
}
|
|
14
100
|
//# sourceMappingURL=utils.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/providers/utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,GAAuB;IACnD,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC;IACjC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,IAAI,CAAC,iDAAiD,EAAE,CAAC,CAAC,CAAC;QACnE,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC"}
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/providers/utils.ts"],"names":[],"mappings":"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"}
|
package/dist/types/request.d.ts
CHANGED
|
@@ -102,6 +102,14 @@ export interface NormalizedRequest {
|
|
|
102
102
|
* Default: 'Claude'
|
|
103
103
|
*/
|
|
104
104
|
assistantParticipant?: string;
|
|
105
|
+
/**
|
|
106
|
+
* Control streaming behavior when calling membrane.stream().
|
|
107
|
+
* - true or undefined: use streaming (default)
|
|
108
|
+
* - false: force non-streaming — membrane.stream() will internally use
|
|
109
|
+
* complete() and synthesize streaming callbacks from the full response.
|
|
110
|
+
* Useful for working around provider streaming bugs.
|
|
111
|
+
*/
|
|
112
|
+
streaming?: boolean;
|
|
105
113
|
/** Provider-specific parameters (pass-through) */
|
|
106
114
|
providerParams?: Record<string, unknown>;
|
|
107
115
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../src/types/request.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAMjD,MAAM,WAAW,gBAAgB;IAC/B,uBAAuB;IACvB,KAAK,EAAE,MAAM,CAAC;IAEd,iCAAiC;IACjC,SAAS,EAAE,MAAM,CAAC;IAElB,wBAAwB;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,6BAA6B;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,yCAAyC;IACzC,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,2CAA2C;IAC3C,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,4CAA4C;IAC5C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B,qCAAqC;IACrC,QAAQ,CAAC,EAAE;QACT,OAAO,EAAE,OAAO,CAAC;QACjB,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,CAAC;IAEF,uCAAuC;IACvC,eAAe,CAAC,EAAE;QAChB,OAAO,EAAE,OAAO,CAAC;QACjB,UAAU,EAAE,CAAC,MAAM,GAAG,OAAO,CAAC,EAAE,CAAC;QACjC,WAAW,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,CAAC;QACtD,SAAS,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;KAC1C,CAAC;CACH;AAMD,MAAM,MAAM,oBAAoB,GAC5B,MAAM,GACN,YAAY,GACZ,oBAAoB,CAAC;AAEzB,MAAM,WAAW,kBAAkB;IACjC,4BAA4B;IAC5B,SAAS,EAAE,MAAM,EAAE,CAAC;IAEpB,4CAA4C;IAC5C,QAAQ,CAAC,EAAE,oBAAoB,CAAC;IAEhC,wDAAwD;IACxD,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,qEAAqE;IACrE,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAMD,MAAM,WAAW,cAAc;IAC7B,oCAAoC;IACpC,MAAM,CAAC,EAAE,WAAW,CAAC;IAErB,sCAAsC;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,iCAAiC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,qCAAqC;IACrC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B;AAMD,MAAM,MAAM,QAAQ,GAChB,KAAK,GACL,QAAQ,GACR,MAAM,CAAC;AAMX,MAAM,WAAW,iBAAiB;IAChC,4BAA4B;IAC5B,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAE9B,oBAAoB;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,+BAA+B;IAC/B,MAAM,EAAE,gBAAgB,CAAC;IAEzB,uBAAuB;IACvB,KAAK,CAAC,EAAE,cAAc,EAAE,CAAC;IAEzB,4CAA4C;IAC5C,QAAQ,CAAC,EAAE,QAAQ,CAAC;IAEpB,kCAAkC;IAClC,aAAa,CAAC,EAAE,kBAAkB,GAAG,MAAM,EAAE,CAAC;IAE9C;;;;OAIG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAEhC;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IAEvB;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAE5B;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAE9B,kDAAkD;IAClD,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC1C"}
|
|
1
|
+
{"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../src/types/request.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/providers/bedrock.ts
CHANGED
|
@@ -533,8 +533,9 @@ export class BedrockAdapter implements ProviderAdapter {
|
|
|
533
533
|
const payloadEnd = totalLength - 4;
|
|
534
534
|
const payloadBytes = buffer.slice(payloadStart, payloadEnd);
|
|
535
535
|
|
|
536
|
-
// Parse headers to find event type
|
|
536
|
+
// Parse headers to find event type and exception type
|
|
537
537
|
let eventType = '';
|
|
538
|
+
let exceptionType = '';
|
|
538
539
|
let headerOffset = 12;
|
|
539
540
|
const headerEnd = 12 + headersLength;
|
|
540
541
|
while (headerOffset < headerEnd) {
|
|
@@ -554,6 +555,8 @@ export class BedrockAdapter implements ProviderAdapter {
|
|
|
554
555
|
|
|
555
556
|
if (name === ':event-type') {
|
|
556
557
|
eventType = value;
|
|
558
|
+
} else if (name === ':exception-type') {
|
|
559
|
+
exceptionType = value;
|
|
557
560
|
}
|
|
558
561
|
} else {
|
|
559
562
|
// Skip other header types
|
|
@@ -561,6 +564,21 @@ export class BedrockAdapter implements ProviderAdapter {
|
|
|
561
564
|
}
|
|
562
565
|
}
|
|
563
566
|
|
|
567
|
+
// Handle exception events from Bedrock (throttling, model errors, etc.)
|
|
568
|
+
if (exceptionType) {
|
|
569
|
+
let errorMessage = exceptionType;
|
|
570
|
+
try {
|
|
571
|
+
const exPayload = JSON.parse(new TextDecoder().decode(payloadBytes));
|
|
572
|
+
errorMessage = exPayload.message || exPayload.Message || exceptionType;
|
|
573
|
+
} catch {
|
|
574
|
+
// Use exception type as message
|
|
575
|
+
}
|
|
576
|
+
throw new BedrockError(
|
|
577
|
+
exceptionType.toLowerCase().includes('throttl') ? 429 : 500,
|
|
578
|
+
`Bedrock stream error (${exceptionType}): ${errorMessage}`
|
|
579
|
+
);
|
|
580
|
+
}
|
|
581
|
+
|
|
564
582
|
// Parse the JSON payload
|
|
565
583
|
if (eventType === 'chunk' && payloadBytes.length > 0) {
|
|
566
584
|
try {
|
|
@@ -575,6 +593,14 @@ export class BedrockAdapter implements ProviderAdapter {
|
|
|
575
593
|
}
|
|
576
594
|
const eventData = JSON.parse(new TextDecoder().decode(bytes)) as BedrockStreamEvent;
|
|
577
595
|
|
|
596
|
+
// Check for error events within the stream
|
|
597
|
+
if (eventData.type === 'error') {
|
|
598
|
+
throw new BedrockError(
|
|
599
|
+
500,
|
|
600
|
+
`Bedrock stream error: ${(eventData as any).error?.message || JSON.stringify(eventData)}`
|
|
601
|
+
);
|
|
602
|
+
}
|
|
603
|
+
|
|
578
604
|
if (eventData.type === 'message_start' && eventData.message) {
|
|
579
605
|
inputTokens = eventData.message.usage?.input_tokens ?? 0;
|
|
580
606
|
} else if (eventData.type === 'content_block_start') {
|
|
@@ -607,8 +633,11 @@ export class BedrockAdapter implements ProviderAdapter {
|
|
|
607
633
|
}
|
|
608
634
|
}
|
|
609
635
|
}
|
|
610
|
-
} catch {
|
|
611
|
-
//
|
|
636
|
+
} catch (e) {
|
|
637
|
+
// Re-throw BedrockErrors (from error events above)
|
|
638
|
+
if (e instanceof BedrockError) throw e;
|
|
639
|
+
// Skip genuinely malformed events (e.g. truncated JSON)
|
|
640
|
+
console.warn('[membrane:bedrock] Skipping malformed stream event:', e);
|
|
612
641
|
}
|
|
613
642
|
}
|
|
614
643
|
|
|
@@ -620,6 +649,14 @@ export class BedrockAdapter implements ProviderAdapter {
|
|
|
620
649
|
reader.releaseLock();
|
|
621
650
|
}
|
|
622
651
|
|
|
652
|
+
// Detect empty responses — Bedrock returned no content and no tokens
|
|
653
|
+
if (contentBlocks.length === 0 && inputTokens === 0 && outputTokens === 0) {
|
|
654
|
+
throw new BedrockError(
|
|
655
|
+
500,
|
|
656
|
+
'Bedrock returned empty response: no content blocks, 0 input/output tokens. This may indicate a transient service issue.'
|
|
657
|
+
);
|
|
658
|
+
}
|
|
659
|
+
|
|
623
660
|
// Build response from accumulated data
|
|
624
661
|
finalMessage = {
|
|
625
662
|
id: 'msg_stream',
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pseudo-Prefill Formatter
|
|
3
|
-
*
|
|
4
|
-
* Recovers prefill-like behavior for models that don't support native
|
|
5
|
-
* assistant message prefill (e.g., Sonnet 4.6, Opus 4.6). Uses a CLI
|
|
6
|
-
* simulation framing trick:
|
|
7
|
-
*
|
|
8
|
-
* System: "The assistant is in CLI simulation mode..."
|
|
9
|
-
* User: "<cmd>cut -c 1-N < conversation.txt</cmd>"
|
|
10
|
-
* Assistant: <the full conversation log, N chars>
|
|
11
|
-
* User: "<cmd>cat conversation.txt</cmd>" (or cut -c N+1-)
|
|
12
|
-
* <model continues from where the cut output ended>
|
|
13
|
-
*
|
|
14
|
-
* Two continuation modes:
|
|
15
|
-
* - 'cat': model repeats full file then continues (reliable, caller strips log)
|
|
16
|
-
* - 'tail-cut': model outputs only new content (efficient, needs simulated stops)
|
|
17
|
-
*
|
|
18
|
-
* IMPORTANT: API-level stop sequences should NOT be used with pseudo-prefill.
|
|
19
|
-
* In 'cat' mode, the model repeats participant names from the log which would
|
|
20
|
-
* trigger stops prematurely. The caller should handle stop sequences post-facto
|
|
21
|
-
* after stripping the repeated log. The stop sequences returned in BuildResult
|
|
22
|
-
* are for the caller's post-facto detection, not for the API.
|
|
23
|
-
*
|
|
24
|
-
* Uses PassthroughParser and native API tools (same as NativeFormatter).
|
|
25
|
-
*/
|
|
26
|
-
import type { NormalizedMessage, ContentBlock, ToolCall, ToolResult } from '../types/index.js';
|
|
27
|
-
import type { PrefillFormatter, StreamParser, BuildOptions, BuildResult, FormatterConfig } from './types.js';
|
|
28
|
-
export interface PseudoPrefillFormatterConfig extends FormatterConfig {
|
|
29
|
-
/**
|
|
30
|
-
* Filename used in the CLI simulation commands.
|
|
31
|
-
* Default: 'conversation.txt'
|
|
32
|
-
*/
|
|
33
|
-
filename?: string;
|
|
34
|
-
/**
|
|
35
|
-
* Continuation mode:
|
|
36
|
-
* - 'cat': `cat filename` — model repeats full file then continues.
|
|
37
|
-
* More reliable but uses more output tokens. Caller must strip the
|
|
38
|
-
* repeated conversation log from the response.
|
|
39
|
-
* - 'tail-cut': `cut -c N+1- < filename` — model outputs only new content.
|
|
40
|
-
* More efficient but may be less reliable. Caller needs simulated stop
|
|
41
|
-
* sequences (only after \n\n, not at position 0).
|
|
42
|
-
* Default: 'cat'
|
|
43
|
-
*/
|
|
44
|
-
continuationMode?: 'cat' | 'tail-cut';
|
|
45
|
-
/**
|
|
46
|
-
* Maximum participants to include in stop sequences.
|
|
47
|
-
* Default: 10
|
|
48
|
-
*/
|
|
49
|
-
maxParticipantsForStop?: number;
|
|
50
|
-
/**
|
|
51
|
-
* Message delimiter between participant entries.
|
|
52
|
-
* Default: '' (none, just newlines)
|
|
53
|
-
*/
|
|
54
|
-
messageDelimiter?: string;
|
|
55
|
-
}
|
|
56
|
-
export declare class PseudoPrefillFormatter implements PrefillFormatter {
|
|
57
|
-
readonly name = "pseudo-prefill";
|
|
58
|
-
readonly usesPrefill = false;
|
|
59
|
-
private config;
|
|
60
|
-
constructor(config?: PseudoPrefillFormatterConfig);
|
|
61
|
-
buildMessages(messages: NormalizedMessage[], options: BuildOptions): BuildResult;
|
|
62
|
-
formatToolResults(results: ToolResult[]): string;
|
|
63
|
-
createStreamParser(): StreamParser;
|
|
64
|
-
parseToolCalls(_content: string): ToolCall[];
|
|
65
|
-
hasToolUse(_content: string): boolean;
|
|
66
|
-
parseContentBlocks(content: string): ContentBlock[];
|
|
67
|
-
private extractContent;
|
|
68
|
-
private buildStopSequences;
|
|
69
|
-
private convertToNativeTools;
|
|
70
|
-
}
|
|
71
|
-
//# sourceMappingURL=pseudo-prefill.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pseudo-prefill.d.ts","sourceRoot":"","sources":["../../src/formatters/pseudo-prefill.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,KAAK,EACV,iBAAiB,EACjB,YAAY,EAEZ,QAAQ,EACR,UAAU,EACX,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EACV,gBAAgB,EAChB,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,eAAe,EAMhB,MAAM,YAAY,CAAC;AAMpB,MAAM,WAAW,4BAA6B,SAAQ,eAAe;IACnE;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;;;;;;;OASG;IACH,gBAAgB,CAAC,EAAE,KAAK,GAAG,UAAU,CAAC;IAEtC;;;OAGG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAEhC;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAqGD,qBAAa,sBAAuB,YAAW,gBAAgB;IAC7D,QAAQ,CAAC,IAAI,oBAAoB;IACjC,QAAQ,CAAC,WAAW,SAAS;IAE7B,OAAO,CAAC,MAAM,CAAyC;gBAE3C,MAAM,GAAE,4BAAiC;IAerD,aAAa,CAAC,QAAQ,EAAE,iBAAiB,EAAE,EAAE,OAAO,EAAE,YAAY,GAAG,WAAW;IA+NhF,iBAAiB,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,MAAM;IAahD,kBAAkB,IAAI,YAAY;IAIlC,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ,EAAE;IAK5C,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAKrC,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,EAAE;IAWnD,OAAO,CAAC,cAAc;IAqCtB,OAAO,CAAC,kBAAkB;IA8B1B,OAAO,CAAC,oBAAoB;CAO7B"}
|