@llumiverse/core 0.23.0-dev.20251121 → 0.24.0-dev.202601221707
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 +141 -218
- package/lib/cjs/CompletionStream.js +65 -0
- package/lib/cjs/CompletionStream.js.map +1 -1
- package/lib/cjs/Driver.js +35 -11
- package/lib/cjs/Driver.js.map +1 -1
- package/lib/cjs/conversation-utils.js +457 -0
- package/lib/cjs/conversation-utils.js.map +1 -0
- package/lib/cjs/index.js +1 -0
- package/lib/cjs/index.js.map +1 -1
- package/lib/cjs/stream.js.map +1 -1
- package/lib/esm/CompletionStream.js +65 -0
- package/lib/esm/CompletionStream.js.map +1 -1
- package/lib/esm/Driver.js +35 -11
- package/lib/esm/Driver.js.map +1 -1
- package/lib/esm/conversation-utils.js +447 -0
- package/lib/esm/conversation-utils.js.map +1 -0
- package/lib/esm/index.js +1 -0
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/stream.js.map +1 -1
- package/lib/types/CompletionStream.d.ts.map +1 -1
- package/lib/types/Driver.d.ts +22 -0
- package/lib/types/Driver.d.ts.map +1 -1
- package/lib/types/conversation-utils.d.ts +112 -0
- package/lib/types/conversation-utils.d.ts.map +1 -0
- package/lib/types/index.d.ts +1 -0
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/stream.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/CompletionStream.ts +70 -1
- package/src/Driver.ts +47 -12
- package/src/conversation-utils.ts +497 -0
- package/src/index.ts +1 -0
- package/src/stream.ts +1 -0
- package/lib/tsconfig.tsbuildinfo +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Driver.d.ts","sourceRoot":"","sources":["../../src/Driver.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EACH,OAAO,EACP,UAAU,EACV,qBAAqB,EACrB,gBAAgB,EAChB,UAAU,EACV,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,MAAM,EAEN,kBAAkB,EAClB,aAAa,EACb,aAAa,EACb,WAAW,EACX,eAAe,EACf,qBAAqB,EACxB,MAAM,oBAAoB,CAAC;AAkC5B,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,UAQlE;AAED,MAAM,WAAW,MAAM,CAAC,OAAO,GAAG,OAAO;IAErC;;;;;OAKG;IACH,oBAAoB,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAEtE,YAAY,CAAC,QAAQ,EAAE,aAAa,EAAE,EAAE,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAElF,OAAO,CAAC,QAAQ,EAAE,aAAa,EAAE,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC;IAInG,MAAM,CAAC,QAAQ,EAAE,aAAa,EAAE,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC;IAEjG,aAAa,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAEnF,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAEpD,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAGpD,UAAU,CAAC,MAAM,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IAG5D,mBAAmB,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IAG1C,kBAAkB,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAGvC,kBAAkB,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"Driver.d.ts","sourceRoot":"","sources":["../../src/Driver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utilities for cleaning up conversation objects before storage.
|
|
3
|
+
*
|
|
4
|
+
* These functions strip binary data (Uint8Array) and large base64 strings
|
|
5
|
+
* from conversation objects to prevent JSON.stringify corruption and reduce
|
|
6
|
+
* storage bloat.
|
|
7
|
+
*
|
|
8
|
+
* IMPORTANT: These functions replace entire image/document/video BLOCKS with
|
|
9
|
+
* text placeholders, not just the data. This ensures the conversation remains
|
|
10
|
+
* valid for subsequent API calls.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Metadata stored in conversation objects to track turn numbers for deferred image stripping.
|
|
14
|
+
*/
|
|
15
|
+
export interface ConversationMeta {
|
|
16
|
+
/** Current turn number (incremented each time a message is added) */
|
|
17
|
+
turnNumber: number;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Options for stripping functions
|
|
21
|
+
*/
|
|
22
|
+
export interface StripOptions {
|
|
23
|
+
/**
|
|
24
|
+
* Number of turns to keep images before stripping.
|
|
25
|
+
* - 0 or undefined: Strip immediately (default)
|
|
26
|
+
* - N > 0: Keep images for N turns, then strip
|
|
27
|
+
*/
|
|
28
|
+
keepForTurns?: number;
|
|
29
|
+
/**
|
|
30
|
+
* Current turn number. Used with keepForTurns to determine when to strip.
|
|
31
|
+
* If not provided, will be read from conversation metadata.
|
|
32
|
+
*/
|
|
33
|
+
currentTurn?: number;
|
|
34
|
+
/**
|
|
35
|
+
* Maximum tokens for text content in tool results.
|
|
36
|
+
* Text exceeding this limit will be truncated.
|
|
37
|
+
* - undefined/0: No truncation (default)
|
|
38
|
+
* - N > 0: Truncate text to approximately N tokens (~4 chars/token)
|
|
39
|
+
*/
|
|
40
|
+
textMaxTokens?: number;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Get metadata from a conversation object, or return defaults.
|
|
44
|
+
*/
|
|
45
|
+
export declare function getConversationMeta(conversation: unknown): ConversationMeta;
|
|
46
|
+
/**
|
|
47
|
+
* Set metadata on a conversation object.
|
|
48
|
+
* Arrays are wrapped in an object to preserve their type through JSON serialization.
|
|
49
|
+
*/
|
|
50
|
+
export declare function setConversationMeta(conversation: unknown, meta: ConversationMeta): unknown;
|
|
51
|
+
/**
|
|
52
|
+
* Unwrap a conversation array that was wrapped by setConversationMeta.
|
|
53
|
+
* If the conversation is not a wrapped array, returns undefined.
|
|
54
|
+
* Use this to extract the actual message array from a conversation object.
|
|
55
|
+
*/
|
|
56
|
+
export declare function unwrapConversationArray<T = unknown>(conversation: unknown): T[] | undefined;
|
|
57
|
+
/**
|
|
58
|
+
* Increment the turn number in a conversation and return the updated conversation.
|
|
59
|
+
*/
|
|
60
|
+
export declare function incrementConversationTurn(conversation: unknown): unknown;
|
|
61
|
+
/**
|
|
62
|
+
* Strip binary data (Uint8Array) from conversation to prevent JSON.stringify corruption.
|
|
63
|
+
*
|
|
64
|
+
* When Uint8Array is passed through JSON.stringify, it gets corrupted into an object
|
|
65
|
+
* like { "0": 137, "1": 80, ... } instead of proper binary data. This breaks
|
|
66
|
+
* subsequent API calls that expect binary data.
|
|
67
|
+
*
|
|
68
|
+
* This function either:
|
|
69
|
+
* - Strips images immediately (keepForTurns = 0, default)
|
|
70
|
+
* - Serializes images to base64 for safe storage, then strips after N turns
|
|
71
|
+
*
|
|
72
|
+
* @param obj The conversation object to strip binary data from
|
|
73
|
+
* @param options Optional settings for turn-based stripping
|
|
74
|
+
* @returns A new object with binary content handled appropriately
|
|
75
|
+
*/
|
|
76
|
+
export declare function stripBinaryFromConversation(obj: unknown, options?: StripOptions): unknown;
|
|
77
|
+
/**
|
|
78
|
+
* Restore Uint8Array from base64 serialization.
|
|
79
|
+
* Call this before sending conversation to API if images were preserved.
|
|
80
|
+
*/
|
|
81
|
+
export declare function deserializeBinaryFromStorage(obj: unknown): unknown;
|
|
82
|
+
/**
|
|
83
|
+
* Strip large base64 image data from conversation to reduce storage bloat.
|
|
84
|
+
*
|
|
85
|
+
* While base64 strings survive JSON.stringify (unlike Uint8Array), they can
|
|
86
|
+
* significantly bloat conversation storage. This function replaces entire
|
|
87
|
+
* image blocks with text placeholders:
|
|
88
|
+
* - OpenAI: { type: "image_url", image_url: { url: "data:..." } } → { type: "text", text: "[placeholder]" }
|
|
89
|
+
* - Gemini: { inlineData: { data: "...", mimeType: "..." } } → { text: "[placeholder]" }
|
|
90
|
+
*
|
|
91
|
+
* @param obj The conversation object to strip base64 images from
|
|
92
|
+
* @param options Optional settings for turn-based stripping
|
|
93
|
+
* @returns A new object with image blocks replaced with text placeholders
|
|
94
|
+
*/
|
|
95
|
+
export declare function stripBase64ImagesFromConversation(obj: unknown, options?: StripOptions): unknown;
|
|
96
|
+
/**
|
|
97
|
+
* Truncate large text content in conversation to reduce storage and context bloat.
|
|
98
|
+
*
|
|
99
|
+
* This function finds text strings in tool results and truncates them if they
|
|
100
|
+
* exceed the specified token limit (using ~4 chars/token estimate).
|
|
101
|
+
*
|
|
102
|
+
* Works with:
|
|
103
|
+
* - Bedrock: toolResult.content[].text
|
|
104
|
+
* - OpenAI: tool message content (string)
|
|
105
|
+
* - Gemini: function response content
|
|
106
|
+
*
|
|
107
|
+
* @param obj The conversation object to truncate text in
|
|
108
|
+
* @param options Options including textMaxTokens
|
|
109
|
+
* @returns A new object with large text content truncated
|
|
110
|
+
*/
|
|
111
|
+
export declare function truncateLargeTextInConversation(obj: unknown, options?: StripOptions): unknown;
|
|
112
|
+
//# sourceMappingURL=conversation-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conversation-utils.d.ts","sourceRoot":"","sources":["../../src/conversation-utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAUH;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC7B,qEAAqE;IACrE,UAAU,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IACzB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B;AAyID;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,OAAO,GAAG,gBAAgB,CAQ3E;AAKD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAS1F;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,CAAC,GAAG,OAAO,EAAE,YAAY,EAAE,OAAO,GAAG,CAAC,EAAE,GAAG,SAAS,CAQ3F;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,YAAY,EAAE,OAAO,GAAG,OAAO,CAGxE;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAYzF;AA2BD;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAwBlE;AAkDD;;;;;;;;;;;;GAYG;AACH,wBAAgB,iCAAiC,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAW/F;AA2CD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,+BAA+B,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAU7F"}
|
package/lib/types/index.d.ts
CHANGED
package/lib/types/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../src/stream.ts"],"names":[],"mappings":"AACA,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAGhF;AAED,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAGhF;AAED,wBAAsB,sBAAsB,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC,
|
|
1
|
+
{"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../src/stream.ts"],"names":[],"mappings":"AACA,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAGhF;AAED,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAGhF;AAED,wBAAsB,sBAAsB,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC,CAmBxF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@llumiverse/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.24.0-dev.202601221707",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Provide an universal API to LLMs. Support for existing LLMs can be added by writing a driver.",
|
|
6
6
|
"files": [
|
|
@@ -63,18 +63,18 @@
|
|
|
63
63
|
"url": "git+ssh://git@github.com/vertesia/llumiverse.git"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
|
-
"@vertesia/api-fetch-client": "^0.79.
|
|
66
|
+
"@vertesia/api-fetch-client": "^0.79.3",
|
|
67
67
|
"rimraf": "^6.1.2",
|
|
68
68
|
"ts-dual-module": "^0.6.3",
|
|
69
69
|
"typescript": "^5.9.3",
|
|
70
|
-
"vitest": "^
|
|
70
|
+
"vitest": "^4.0.16"
|
|
71
71
|
},
|
|
72
72
|
"dependencies": {
|
|
73
73
|
"@types/node": "^22.19.1",
|
|
74
74
|
"ajv": "^8.17.1",
|
|
75
75
|
"ajv-formats": "^3.0.1",
|
|
76
76
|
"jsonrepair": "^3.13.1",
|
|
77
|
-
"@llumiverse/common": "0.
|
|
77
|
+
"@llumiverse/common": "0.24.0-dev.202601221707"
|
|
78
78
|
},
|
|
79
79
|
"ts_dual_module": {
|
|
80
80
|
"outDir": "lib",
|
package/src/CompletionStream.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CompletionStream, DriverOptions, ExecutionOptions, ExecutionResponse, ExecutionTokenUsage } from "@llumiverse/common";
|
|
1
|
+
import { CompletionStream, DriverOptions, ExecutionOptions, ExecutionResponse, ExecutionTokenUsage, ToolUse } from "@llumiverse/common";
|
|
2
2
|
import { AbstractDriver } from "./Driver.js";
|
|
3
3
|
|
|
4
4
|
export class DefaultCompletionStream<PromptT = any> implements CompletionStream<PromptT> {
|
|
@@ -17,6 +17,7 @@ export class DefaultCompletionStream<PromptT = any> implements CompletionStream<
|
|
|
17
17
|
this.completion = undefined;
|
|
18
18
|
this.chunks = 0;
|
|
19
19
|
const accumulatedResults: any[] = []; // Accumulate CompletionResult[] from chunks
|
|
20
|
+
const accumulatedToolUse: Map<string, ToolUse> = new Map(); // Accumulate tool_use by id
|
|
20
21
|
|
|
21
22
|
this.driver.logger.debug(
|
|
22
23
|
`[${this.driver.provider}] Streaming Execution of ${this.options.model} with prompt`,
|
|
@@ -45,6 +46,40 @@ export class DefaultCompletionStream<PromptT = any> implements CompletionStream<
|
|
|
45
46
|
promptTokens = Math.max(promptTokens, chunk.token_usage.prompt ?? 0);
|
|
46
47
|
resultTokens = Math.max(resultTokens ?? 0, chunk.token_usage.result ?? 0);
|
|
47
48
|
}
|
|
49
|
+
// Accumulate tool_use from chunks
|
|
50
|
+
// Note: During streaming, tool_input comes as string chunks that need concatenation
|
|
51
|
+
if (chunk.tool_use && chunk.tool_use.length > 0) {
|
|
52
|
+
for (const tool of chunk.tool_use) {
|
|
53
|
+
const existing = accumulatedToolUse.get(tool.id);
|
|
54
|
+
if (existing) {
|
|
55
|
+
// Merge tool input (for streaming where arguments come as string pieces)
|
|
56
|
+
if (tool.tool_input !== null && tool.tool_input !== undefined) {
|
|
57
|
+
const existingInput = existing.tool_input as unknown;
|
|
58
|
+
const newInput = tool.tool_input as unknown;
|
|
59
|
+
if (typeof existingInput === 'string' && typeof newInput === 'string') {
|
|
60
|
+
// Concatenate string arguments
|
|
61
|
+
(existing as any).tool_input = existingInput + newInput;
|
|
62
|
+
} else if (existingInput && typeof existingInput === 'object' && newInput && typeof newInput === 'object') {
|
|
63
|
+
// Merge objects
|
|
64
|
+
existing.tool_input = { ...(existingInput as object), ...(newInput as object) } as any;
|
|
65
|
+
} else {
|
|
66
|
+
existing.tool_input = tool.tool_input;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// Update tool name if provided (might come in later chunk)
|
|
70
|
+
if (tool.tool_name) {
|
|
71
|
+
existing.tool_name = tool.tool_name;
|
|
72
|
+
}
|
|
73
|
+
// Update actual ID if provided (OpenAI sends id only in first chunk)
|
|
74
|
+
if ((tool as any)._actual_id) {
|
|
75
|
+
(existing as any)._actual_id = (tool as any)._actual_id;
|
|
76
|
+
}
|
|
77
|
+
} else {
|
|
78
|
+
// New tool call
|
|
79
|
+
accumulatedToolUse.set(tool.id, { ...tool });
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
48
83
|
if (Array.isArray(chunk.result) && chunk.result.length > 0) {
|
|
49
84
|
// Process each result in the chunk, combining consecutive text/JSON
|
|
50
85
|
for (const result of chunk.result) {
|
|
@@ -118,6 +153,28 @@ export class DefaultCompletionStream<PromptT = any> implements CompletionStream<
|
|
|
118
153
|
const tokens: ExecutionTokenUsage | undefined = resultTokens ?
|
|
119
154
|
{ prompt: promptTokens, result: resultTokens, total: resultTokens + promptTokens, } : undefined
|
|
120
155
|
|
|
156
|
+
// Convert accumulated tool_use Map to array
|
|
157
|
+
const toolUseArray = accumulatedToolUse.size > 0 ? Array.from(accumulatedToolUse.values()) : undefined;
|
|
158
|
+
|
|
159
|
+
// Finalize tool calls: restore actual IDs and parse JSON arguments
|
|
160
|
+
if (toolUseArray) {
|
|
161
|
+
for (const tool of toolUseArray) {
|
|
162
|
+
// Restore actual ID from OpenAI (was stored in _actual_id during streaming)
|
|
163
|
+
if ((tool as any)._actual_id) {
|
|
164
|
+
tool.id = (tool as any)._actual_id;
|
|
165
|
+
delete (tool as any)._actual_id;
|
|
166
|
+
}
|
|
167
|
+
// Parse tool_input strings as JSON if needed (streaming sends arguments as string chunks)
|
|
168
|
+
if (typeof tool.tool_input === 'string') {
|
|
169
|
+
try {
|
|
170
|
+
tool.tool_input = JSON.parse(tool.tool_input);
|
|
171
|
+
} catch {
|
|
172
|
+
// Keep as string if not valid JSON
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
121
178
|
this.completion = {
|
|
122
179
|
result: accumulatedResults, // Return the accumulated CompletionResult[] instead of text
|
|
123
180
|
prompt: this.prompt,
|
|
@@ -125,6 +182,18 @@ export class DefaultCompletionStream<PromptT = any> implements CompletionStream<
|
|
|
125
182
|
token_usage: tokens,
|
|
126
183
|
finish_reason: finish_reason,
|
|
127
184
|
chunks: this.chunks,
|
|
185
|
+
tool_use: toolUseArray,
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Build conversation context for multi-turn support
|
|
189
|
+
const conversation = this.driver.buildStreamingConversation(
|
|
190
|
+
this.prompt,
|
|
191
|
+
accumulatedResults,
|
|
192
|
+
toolUseArray,
|
|
193
|
+
this.options
|
|
194
|
+
);
|
|
195
|
+
if (conversation !== undefined) {
|
|
196
|
+
this.completion.conversation = conversation;
|
|
128
197
|
}
|
|
129
198
|
|
|
130
199
|
try {
|
package/src/Driver.ts
CHANGED
|
@@ -105,6 +105,11 @@ export interface Driver<PromptT = unknown> {
|
|
|
105
105
|
//generate embeddings for a given text or image
|
|
106
106
|
generateEmbeddings(options: EmbeddingsOptions): Promise<EmbeddingsResult>;
|
|
107
107
|
|
|
108
|
+
/**
|
|
109
|
+
* Optional cleanup method called when the driver is evicted from the cache.
|
|
110
|
+
* Override this in driver implementations that need to release resources.
|
|
111
|
+
*/
|
|
112
|
+
destroy?(): void;
|
|
108
113
|
}
|
|
109
114
|
|
|
110
115
|
/**
|
|
@@ -166,22 +171,19 @@ export abstract class AbstractDriver<OptionsT extends DriverOptions = DriverOpti
|
|
|
166
171
|
}
|
|
167
172
|
|
|
168
173
|
async _execute(prompt: PromptT, options: ExecutionOptions): Promise<ExecutionResponse<PromptT>> {
|
|
169
|
-
this.logger.debug(
|
|
170
|
-
`[${this.provider}] Executing prompt on ${options.model}`);
|
|
171
174
|
try {
|
|
172
175
|
const start = Date.now();
|
|
173
176
|
let result;
|
|
174
177
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
throw new Error(`Unsupported modality: ${options['output_modality'] ?? "No modality specified"}`);
|
|
178
|
+
if (this.isImageModel(options.model)) {
|
|
179
|
+
this.logger.debug(
|
|
180
|
+
`[${this.provider}] Executing prompt on ${options.model}, image pathway.`);
|
|
181
|
+
result = await this.requestImageGeneration(prompt, options);
|
|
182
|
+
} else {
|
|
183
|
+
this.logger.debug(
|
|
184
|
+
`[${this.provider}] Executing prompt on ${options.model}, text pathway.`);
|
|
185
|
+
result = await this.requestTextCompletion(prompt, options);
|
|
186
|
+
this.validateResult(result, options);
|
|
185
187
|
}
|
|
186
188
|
|
|
187
189
|
const execution_time = Date.now() - start;
|
|
@@ -192,12 +194,18 @@ export abstract class AbstractDriver<OptionsT extends DriverOptions = DriverOpti
|
|
|
192
194
|
}
|
|
193
195
|
}
|
|
194
196
|
|
|
197
|
+
protected isImageModel(_model: string): boolean {
|
|
198
|
+
return false;
|
|
199
|
+
}
|
|
200
|
+
|
|
195
201
|
// by default no stream is supported. we block and we return all at once
|
|
196
202
|
async stream(segments: PromptSegment[], options: ExecutionOptions): Promise<CompletionStream<PromptT>> {
|
|
197
203
|
const prompt = await this.createPrompt(segments, options);
|
|
198
204
|
const canStream = await this.canStream(options);
|
|
199
205
|
if (options.output_modality === Modalities.text && canStream) {
|
|
200
206
|
return new DefaultCompletionStream(this, prompt, options);
|
|
207
|
+
} else if (this.isImageModel(options.model)) {
|
|
208
|
+
return new FallbackCompletionStream(this, prompt, options);
|
|
201
209
|
} else {
|
|
202
210
|
return new FallbackCompletionStream(this, prompt, options);
|
|
203
211
|
}
|
|
@@ -239,6 +247,26 @@ export abstract class AbstractDriver<OptionsT extends DriverOptions = DriverOpti
|
|
|
239
247
|
return [];
|
|
240
248
|
}
|
|
241
249
|
|
|
250
|
+
/**
|
|
251
|
+
* Build the conversation context after streaming completion.
|
|
252
|
+
* Override this in driver implementations that support multi-turn conversations.
|
|
253
|
+
*
|
|
254
|
+
* @param prompt - The prompt that was sent (includes prior conversation context)
|
|
255
|
+
* @param result - The completion results from the streamed response
|
|
256
|
+
* @param toolUse - The tool calls from the streamed response (if any)
|
|
257
|
+
* @param options - The execution options
|
|
258
|
+
* @returns The updated conversation context, or undefined if not supported
|
|
259
|
+
*/
|
|
260
|
+
buildStreamingConversation(
|
|
261
|
+
_prompt: PromptT,
|
|
262
|
+
_result: unknown[],
|
|
263
|
+
_toolUse: unknown[] | undefined,
|
|
264
|
+
_options: ExecutionOptions
|
|
265
|
+
): unknown | undefined {
|
|
266
|
+
// Default implementation returns undefined - drivers can override
|
|
267
|
+
return undefined;
|
|
268
|
+
}
|
|
269
|
+
|
|
242
270
|
abstract requestTextCompletion(prompt: PromptT, options: ExecutionOptions): Promise<Completion>;
|
|
243
271
|
|
|
244
272
|
abstract requestTextCompletionStream(prompt: PromptT, options: ExecutionOptions): Promise<AsyncIterable<CompletionChunkObject>>;
|
|
@@ -257,4 +285,11 @@ export abstract class AbstractDriver<OptionsT extends DriverOptions = DriverOpti
|
|
|
257
285
|
//generate embeddings for a given text
|
|
258
286
|
abstract generateEmbeddings(options: EmbeddingsOptions): Promise<EmbeddingsResult>;
|
|
259
287
|
|
|
288
|
+
/**
|
|
289
|
+
* Cleanup method called when the driver is evicted from the cache.
|
|
290
|
+
* Override this in driver implementations that need to release resources.
|
|
291
|
+
*/
|
|
292
|
+
destroy(): void {
|
|
293
|
+
// No-op by default
|
|
294
|
+
}
|
|
260
295
|
}
|