@llumiverse/drivers 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/azure/azure_foundry.js +46 -2
- package/lib/cjs/azure/azure_foundry.js.map +1 -1
- package/lib/cjs/bedrock/index.js +239 -19
- package/lib/cjs/bedrock/index.js.map +1 -1
- package/lib/cjs/groq/index.js +115 -85
- package/lib/cjs/groq/index.js.map +1 -1
- package/lib/cjs/index.js +1 -0
- package/lib/cjs/index.js.map +1 -1
- package/lib/cjs/openai/index.js +310 -114
- package/lib/cjs/openai/index.js.map +1 -1
- package/lib/cjs/openai/openai_compatible.js +62 -0
- package/lib/cjs/openai/openai_compatible.js.map +1 -0
- package/lib/cjs/openai/openai_format.js +32 -39
- package/lib/cjs/openai/openai_format.js.map +1 -1
- package/lib/cjs/vertexai/index.js +211 -5
- package/lib/cjs/vertexai/index.js.map +1 -1
- package/lib/cjs/vertexai/models/claude.js +201 -3
- package/lib/cjs/vertexai/models/claude.js.map +1 -1
- package/lib/cjs/vertexai/models/gemini.js +74 -25
- package/lib/cjs/vertexai/models/gemini.js.map +1 -1
- package/lib/cjs/vertexai/models/imagen.js +0 -3
- package/lib/cjs/vertexai/models/imagen.js.map +1 -1
- package/lib/cjs/xai/index.js +10 -16
- package/lib/cjs/xai/index.js.map +1 -1
- package/lib/esm/azure/azure_foundry.js +46 -2
- package/lib/esm/azure/azure_foundry.js.map +1 -1
- package/lib/esm/bedrock/index.js +239 -20
- package/lib/esm/bedrock/index.js.map +1 -1
- package/lib/esm/groq/index.js +115 -85
- package/lib/esm/groq/index.js.map +1 -1
- package/lib/esm/index.js +1 -0
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/openai/index.js +311 -115
- package/lib/esm/openai/index.js.map +1 -1
- package/lib/esm/openai/openai_compatible.js +55 -0
- package/lib/esm/openai/openai_compatible.js.map +1 -0
- package/lib/esm/openai/openai_format.js +32 -39
- package/lib/esm/openai/openai_format.js.map +1 -1
- package/lib/esm/vertexai/index.js +212 -6
- package/lib/esm/vertexai/index.js.map +1 -1
- package/lib/esm/vertexai/models/claude.js +199 -3
- package/lib/esm/vertexai/models/claude.js.map +1 -1
- package/lib/esm/vertexai/models/gemini.js +75 -26
- package/lib/esm/vertexai/models/gemini.js.map +1 -1
- package/lib/esm/vertexai/models/imagen.js +1 -4
- package/lib/esm/vertexai/models/imagen.js.map +1 -1
- package/lib/esm/xai/index.js +10 -16
- package/lib/esm/xai/index.js.map +1 -1
- package/lib/types/azure/azure_foundry.d.ts +7 -5
- package/lib/types/azure/azure_foundry.d.ts.map +1 -1
- package/lib/types/bedrock/index.d.ts +22 -1
- package/lib/types/bedrock/index.d.ts.map +1 -1
- package/lib/types/groq/index.d.ts.map +1 -1
- package/lib/types/index.d.ts +1 -0
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/openai/index.d.ts +13 -7
- package/lib/types/openai/index.d.ts.map +1 -1
- package/lib/types/openai/openai_compatible.d.ts +26 -0
- package/lib/types/openai/openai_compatible.d.ts.map +1 -0
- package/lib/types/openai/openai_format.d.ts +4 -2
- package/lib/types/openai/openai_format.d.ts.map +1 -1
- package/lib/types/vertexai/index.d.ts +16 -0
- package/lib/types/vertexai/index.d.ts.map +1 -1
- package/lib/types/vertexai/models/claude.d.ts +20 -0
- package/lib/types/vertexai/models/claude.d.ts.map +1 -1
- package/lib/types/vertexai/models/gemini.d.ts +1 -1
- package/lib/types/vertexai/models/gemini.d.ts.map +1 -1
- package/lib/types/vertexai/models/imagen.d.ts.map +1 -1
- package/lib/types/xai/index.d.ts +2 -3
- package/lib/types/xai/index.d.ts.map +1 -1
- package/package.json +17 -17
- package/src/azure/azure_foundry.ts +56 -7
- package/src/bedrock/index.ts +301 -29
- package/src/groq/index.ts +120 -94
- package/src/index.ts +1 -0
- package/src/openai/index.ts +363 -136
- package/src/openai/openai_compatible.ts +74 -0
- package/src/openai/openai_format.ts +44 -54
- package/src/vertexai/index.ts +255 -6
- package/src/vertexai/models/claude.ts +233 -3
- package/src/vertexai/models/gemini.ts +95 -32
- package/src/vertexai/models/imagen.ts +1 -5
- package/src/xai/index.ts +10 -17
- package/lib/cjs/test/TestErrorCompletionStream.js +0 -20
- package/lib/cjs/test/TestErrorCompletionStream.js.map +0 -1
- package/lib/cjs/test/TestValidationErrorCompletionStream.js +0 -24
- package/lib/cjs/test/TestValidationErrorCompletionStream.js.map +0 -1
- package/lib/cjs/test/index.js +0 -109
- package/lib/cjs/test/index.js.map +0 -1
- package/lib/cjs/test/utils.js +0 -30
- package/lib/cjs/test/utils.js.map +0 -1
- package/lib/esm/src/adobe/firefly.js +0 -116
- package/lib/esm/src/adobe/firefly.js.map +0 -1
- package/lib/esm/src/azure/azure_foundry.js +0 -382
- package/lib/esm/src/azure/azure_foundry.js.map +0 -1
- package/lib/esm/src/bedrock/converse.js +0 -278
- package/lib/esm/src/bedrock/converse.js.map +0 -1
- package/lib/esm/src/bedrock/index.js +0 -962
- package/lib/esm/src/bedrock/index.js.map +0 -1
- package/lib/esm/src/bedrock/nova-image-payload.js +0 -203
- package/lib/esm/src/bedrock/nova-image-payload.js.map +0 -1
- package/lib/esm/src/bedrock/payloads.js +0 -2
- package/lib/esm/src/bedrock/payloads.js.map +0 -1
- package/lib/esm/src/bedrock/s3.js +0 -99
- package/lib/esm/src/bedrock/s3.js.map +0 -1
- package/lib/esm/src/bedrock/twelvelabs.js +0 -84
- package/lib/esm/src/bedrock/twelvelabs.js.map +0 -1
- package/lib/esm/src/groq/index.js +0 -286
- package/lib/esm/src/groq/index.js.map +0 -1
- package/lib/esm/src/huggingface_ie.js +0 -197
- package/lib/esm/src/huggingface_ie.js.map +0 -1
- package/lib/esm/src/index.js +0 -14
- package/lib/esm/src/index.js.map +0 -1
- package/lib/esm/src/mistral/index.js +0 -169
- package/lib/esm/src/mistral/index.js.map +0 -1
- package/lib/esm/src/mistral/types.js +0 -80
- package/lib/esm/src/mistral/types.js.map +0 -1
- package/lib/esm/src/openai/azure_openai.js +0 -68
- package/lib/esm/src/openai/azure_openai.js.map +0 -1
- package/lib/esm/src/openai/index.js +0 -464
- package/lib/esm/src/openai/index.js.map +0 -1
- package/lib/esm/src/openai/openai.js +0 -14
- package/lib/esm/src/openai/openai.js.map +0 -1
- package/lib/esm/src/openai/openai_format.js +0 -134
- package/lib/esm/src/openai/openai_format.js.map +0 -1
- package/lib/esm/src/replicate.js +0 -268
- package/lib/esm/src/replicate.js.map +0 -1
- package/lib/esm/src/test/TestErrorCompletionStream.js +0 -16
- package/lib/esm/src/test/TestErrorCompletionStream.js.map +0 -1
- package/lib/esm/src/test/TestValidationErrorCompletionStream.js +0 -20
- package/lib/esm/src/test/TestValidationErrorCompletionStream.js.map +0 -1
- package/lib/esm/src/test/index.js +0 -91
- package/lib/esm/src/test/index.js.map +0 -1
- package/lib/esm/src/test/utils.js +0 -25
- package/lib/esm/src/test/utils.js.map +0 -1
- package/lib/esm/src/test-driver/TestErrorCompletionStream.js +0 -16
- package/lib/esm/src/test-driver/TestErrorCompletionStream.js.map +0 -1
- package/lib/esm/src/test-driver/TestValidationErrorCompletionStream.js +0 -20
- package/lib/esm/src/test-driver/TestValidationErrorCompletionStream.js.map +0 -1
- package/lib/esm/src/test-driver/index.js +0 -91
- package/lib/esm/src/test-driver/index.js.map +0 -1
- package/lib/esm/src/test-driver/utils.js +0 -25
- package/lib/esm/src/test-driver/utils.js.map +0 -1
- package/lib/esm/src/togetherai/index.js +0 -122
- package/lib/esm/src/togetherai/index.js.map +0 -1
- package/lib/esm/src/togetherai/interfaces.js +0 -2
- package/lib/esm/src/togetherai/interfaces.js.map +0 -1
- package/lib/esm/src/vertexai/debug.js +0 -6
- package/lib/esm/src/vertexai/debug.js.map +0 -1
- package/lib/esm/src/vertexai/embeddings/embeddings-image.js +0 -24
- package/lib/esm/src/vertexai/embeddings/embeddings-image.js.map +0 -1
- package/lib/esm/src/vertexai/embeddings/embeddings-text.js +0 -20
- package/lib/esm/src/vertexai/embeddings/embeddings-text.js.map +0 -1
- package/lib/esm/src/vertexai/index.js +0 -383
- package/lib/esm/src/vertexai/index.js.map +0 -1
- package/lib/esm/src/vertexai/models/claude.js +0 -394
- package/lib/esm/src/vertexai/models/claude.js.map +0 -1
- package/lib/esm/src/vertexai/models/gemini.js +0 -817
- package/lib/esm/src/vertexai/models/gemini.js.map +0 -1
- package/lib/esm/src/vertexai/models/imagen.js +0 -302
- package/lib/esm/src/vertexai/models/imagen.js.map +0 -1
- package/lib/esm/src/vertexai/models/llama.js +0 -179
- package/lib/esm/src/vertexai/models/llama.js.map +0 -1
- package/lib/esm/src/vertexai/models.js +0 -32
- package/lib/esm/src/vertexai/models.js.map +0 -1
- package/lib/esm/src/watsonx/index.js +0 -157
- package/lib/esm/src/watsonx/index.js.map +0 -1
- package/lib/esm/src/watsonx/interfaces.js +0 -2
- package/lib/esm/src/watsonx/interfaces.js.map +0 -1
- package/lib/esm/src/xai/index.js +0 -64
- package/lib/esm/src/xai/index.js.map +0 -1
- package/lib/esm/test/TestErrorCompletionStream.js +0 -16
- package/lib/esm/test/TestErrorCompletionStream.js.map +0 -1
- package/lib/esm/test/TestValidationErrorCompletionStream.js +0 -20
- package/lib/esm/test/TestValidationErrorCompletionStream.js.map +0 -1
- package/lib/esm/test/index.js +0 -91
- package/lib/esm/test/index.js.map +0 -1
- package/lib/esm/test/utils.js +0 -25
- package/lib/esm/test/utils.js.map +0 -1
- package/lib/esm/tsconfig.tsbuildinfo +0 -1
- package/lib/types/src/adobe/firefly.d.ts +0 -29
- package/lib/types/src/azure/azure_foundry.d.ts +0 -49
- package/lib/types/src/bedrock/converse.d.ts +0 -8
- package/lib/types/src/bedrock/index.d.ts +0 -61
- package/lib/types/src/bedrock/nova-image-payload.d.ts +0 -73
- package/lib/types/src/bedrock/payloads.d.ts +0 -11
- package/lib/types/src/bedrock/s3.d.ts +0 -22
- package/lib/types/src/bedrock/twelvelabs.d.ts +0 -49
- package/lib/types/src/groq/index.d.ts +0 -26
- package/lib/types/src/huggingface_ie.d.ts +0 -34
- package/lib/types/src/index.d.ts +0 -13
- package/lib/types/src/mistral/index.d.ts +0 -24
- package/lib/types/src/mistral/types.d.ts +0 -131
- package/lib/types/src/openai/azure_openai.d.ts +0 -24
- package/lib/types/src/openai/index.d.ts +0 -24
- package/lib/types/src/openai/openai.d.ts +0 -14
- package/lib/types/src/openai/openai_format.d.ts +0 -18
- package/lib/types/src/replicate.d.ts +0 -47
- package/lib/types/src/test/TestErrorCompletionStream.d.ts +0 -8
- package/lib/types/src/test/TestValidationErrorCompletionStream.d.ts +0 -8
- package/lib/types/src/test/index.d.ts +0 -23
- package/lib/types/src/test/utils.d.ts +0 -4
- package/lib/types/src/test-driver/TestErrorCompletionStream.d.ts +0 -8
- package/lib/types/src/test-driver/TestValidationErrorCompletionStream.d.ts +0 -8
- package/lib/types/src/test-driver/index.d.ts +0 -23
- package/lib/types/src/test-driver/utils.d.ts +0 -4
- package/lib/types/src/togetherai/index.d.ts +0 -22
- package/lib/types/src/togetherai/interfaces.d.ts +0 -95
- package/lib/types/src/vertexai/debug.d.ts +0 -1
- package/lib/types/src/vertexai/embeddings/embeddings-image.d.ts +0 -10
- package/lib/types/src/vertexai/embeddings/embeddings-text.d.ts +0 -9
- package/lib/types/src/vertexai/index.d.ts +0 -52
- package/lib/types/src/vertexai/models/claude.d.ts +0 -19
- package/lib/types/src/vertexai/models/gemini.d.ts +0 -17
- package/lib/types/src/vertexai/models/imagen.d.ts +0 -74
- package/lib/types/src/vertexai/models/llama.d.ts +0 -19
- package/lib/types/src/vertexai/models.d.ts +0 -14
- package/lib/types/src/watsonx/index.d.ts +0 -26
- package/lib/types/src/watsonx/interfaces.d.ts +0 -64
- package/lib/types/src/xai/index.d.ts +0 -18
- package/lib/types/test/TestErrorCompletionStream.d.ts +0 -9
- package/lib/types/test/TestErrorCompletionStream.d.ts.map +0 -1
- package/lib/types/test/TestValidationErrorCompletionStream.d.ts +0 -9
- package/lib/types/test/TestValidationErrorCompletionStream.d.ts.map +0 -1
- package/lib/types/test/index.d.ts +0 -24
- package/lib/types/test/index.d.ts.map +0 -1
- package/lib/types/test/utils.d.ts +0 -5
- package/lib/types/test/utils.d.ts.map +0 -1
|
@@ -321,11 +321,17 @@ export class ClaudeModelDefinition implements ModelDefinition<ClaudePrompt> {
|
|
|
321
321
|
driver.logger.warn({ options: options.model_options }, "Invalid model options");
|
|
322
322
|
}
|
|
323
323
|
|
|
324
|
-
|
|
324
|
+
// Include conversation history (same as non-streaming)
|
|
325
|
+
const conversation = updateConversation(options.conversation as ClaudePrompt, prompt);
|
|
326
|
+
|
|
327
|
+
const { payload, requestOptions } = getClaudePayload(options, conversation);
|
|
325
328
|
const streamingPayload: MessageStreamParams = { ...payload, stream: true };
|
|
326
329
|
|
|
327
330
|
const response_stream = await client.messages.stream(streamingPayload, requestOptions);
|
|
328
331
|
|
|
332
|
+
// Track current tool use being built from streaming
|
|
333
|
+
let currentToolUse: { id: string; name: string; inputJson: string } | null = null;
|
|
334
|
+
|
|
329
335
|
const stream = asyncMap(response_stream, async (streamEvent: RawMessageStreamEvent) => {
|
|
330
336
|
switch (streamEvent.type) {
|
|
331
337
|
case "message_start":
|
|
@@ -345,6 +351,22 @@ export class ClaudeModelDefinition implements ModelDefinition<ClaudePrompt> {
|
|
|
345
351
|
finish_reason: claudeFinishReason(streamEvent.delta.stop_reason ?? undefined),
|
|
346
352
|
} satisfies CompletionChunkObject;
|
|
347
353
|
case "content_block_start":
|
|
354
|
+
// Handle tool_use blocks
|
|
355
|
+
if (streamEvent.content_block.type === "tool_use") {
|
|
356
|
+
currentToolUse = {
|
|
357
|
+
id: streamEvent.content_block.id,
|
|
358
|
+
name: streamEvent.content_block.name,
|
|
359
|
+
inputJson: ''
|
|
360
|
+
};
|
|
361
|
+
return {
|
|
362
|
+
result: [],
|
|
363
|
+
tool_use: [{
|
|
364
|
+
id: streamEvent.content_block.id,
|
|
365
|
+
tool_name: streamEvent.content_block.name,
|
|
366
|
+
tool_input: '' as any // Will be accumulated via input_json_delta
|
|
367
|
+
}]
|
|
368
|
+
} satisfies CompletionChunkObject;
|
|
369
|
+
}
|
|
348
370
|
// Handle redacted thinking blocks
|
|
349
371
|
if (streamEvent.content_block.type === "redacted_thinking" && model_options?.include_thoughts) {
|
|
350
372
|
return {
|
|
@@ -359,6 +381,19 @@ export class ClaudeModelDefinition implements ModelDefinition<ClaudePrompt> {
|
|
|
359
381
|
return {
|
|
360
382
|
result: streamEvent.delta.text ? [{ type: "text", value: streamEvent.delta.text }] : []
|
|
361
383
|
} satisfies CompletionChunkObject;
|
|
384
|
+
case "input_json_delta":
|
|
385
|
+
// Accumulate tool input JSON
|
|
386
|
+
if (currentToolUse && streamEvent.delta.partial_json) {
|
|
387
|
+
return {
|
|
388
|
+
result: [],
|
|
389
|
+
tool_use: [{
|
|
390
|
+
id: currentToolUse.id,
|
|
391
|
+
tool_name: '', // Name already sent in content_block_start
|
|
392
|
+
tool_input: streamEvent.delta.partial_json as any
|
|
393
|
+
}]
|
|
394
|
+
} satisfies CompletionChunkObject;
|
|
395
|
+
}
|
|
396
|
+
break;
|
|
362
397
|
case "thinking_delta":
|
|
363
398
|
if (model_options?.include_thoughts) {
|
|
364
399
|
return {
|
|
@@ -377,6 +412,10 @@ export class ClaudeModelDefinition implements ModelDefinition<ClaudePrompt> {
|
|
|
377
412
|
}
|
|
378
413
|
break;
|
|
379
414
|
case "content_block_stop":
|
|
415
|
+
// Reset current tool use tracking when block ends
|
|
416
|
+
if (currentToolUse) {
|
|
417
|
+
currentToolUse = null;
|
|
418
|
+
}
|
|
380
419
|
// Handle the end of content blocks, for redacted thinking blocks
|
|
381
420
|
if (model_options?.include_thoughts) {
|
|
382
421
|
return {
|
|
@@ -406,6 +445,60 @@ function createPromptFromResponse(response: Message): ClaudePrompt {
|
|
|
406
445
|
}
|
|
407
446
|
}
|
|
408
447
|
|
|
448
|
+
/**
|
|
449
|
+
* Merge consecutive user messages in the conversation.
|
|
450
|
+
* This is required because Anthropic's API expects all tool_result blocks
|
|
451
|
+
* from a single assistant turn to be in one user message.
|
|
452
|
+
* When multiple tool results are added as separate user messages,
|
|
453
|
+
* we need to merge them before sending to the API.
|
|
454
|
+
*/
|
|
455
|
+
export function mergeConsecutiveUserMessages(messages: MessageParam[]): MessageParam[] {
|
|
456
|
+
if (messages.length === 0) return [];
|
|
457
|
+
|
|
458
|
+
// Check if any merging is needed
|
|
459
|
+
const needsMerging = messages.some((msg, i) =>
|
|
460
|
+
i < messages.length - 1 &&
|
|
461
|
+
msg.role === 'user' &&
|
|
462
|
+
messages[i + 1].role === 'user'
|
|
463
|
+
);
|
|
464
|
+
|
|
465
|
+
if (!needsMerging) {
|
|
466
|
+
return messages;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
const result: MessageParam[] = [];
|
|
470
|
+
let i = 0;
|
|
471
|
+
|
|
472
|
+
while (i < messages.length) {
|
|
473
|
+
const current = messages[i];
|
|
474
|
+
|
|
475
|
+
if (current.role === 'user') {
|
|
476
|
+
// Collect all consecutive user messages
|
|
477
|
+
const mergedContent: MessageParam['content'] = [];
|
|
478
|
+
|
|
479
|
+
while (i < messages.length && messages[i].role === 'user') {
|
|
480
|
+
const userMsg = messages[i];
|
|
481
|
+
if (Array.isArray(userMsg.content)) {
|
|
482
|
+
mergedContent.push(...userMsg.content);
|
|
483
|
+
} else if (typeof userMsg.content === 'string') {
|
|
484
|
+
mergedContent.push({ type: 'text', text: userMsg.content });
|
|
485
|
+
}
|
|
486
|
+
i++;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
result.push({
|
|
490
|
+
role: 'user',
|
|
491
|
+
content: mergedContent
|
|
492
|
+
});
|
|
493
|
+
} else {
|
|
494
|
+
result.push(current);
|
|
495
|
+
i++;
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
return result;
|
|
500
|
+
}
|
|
501
|
+
|
|
409
502
|
/**
|
|
410
503
|
* Update the conversation messages
|
|
411
504
|
* @param prompt
|
|
@@ -416,11 +509,143 @@ function updateConversation(conversation: ClaudePrompt | undefined | null, promp
|
|
|
416
509
|
const baseSystemMessages = conversation?.system || [];
|
|
417
510
|
const baseMessages = conversation?.messages || [];
|
|
418
511
|
const system = baseSystemMessages.concat(prompt.system || []);
|
|
512
|
+
// Merge consecutive user messages to ensure tool_result blocks are properly grouped
|
|
513
|
+
const mergedMessages = mergeConsecutiveUserMessages(baseMessages.concat(prompt.messages || []));
|
|
419
514
|
return {
|
|
420
|
-
messages:
|
|
515
|
+
messages: mergedMessages,
|
|
421
516
|
system: system.length > 0 ? system : undefined // If system is empty, set to undefined
|
|
422
517
|
};
|
|
423
518
|
}
|
|
519
|
+
|
|
520
|
+
/**
|
|
521
|
+
* Sanitize messages by removing empty text blocks.
|
|
522
|
+
* Claude API rejects messages with empty text content blocks ("text content blocks must be non-empty").
|
|
523
|
+
* This handles cases where streaming was interrupted and left empty text blocks.
|
|
524
|
+
*
|
|
525
|
+
* - Filters out empty text blocks from each message's content
|
|
526
|
+
* - Removes messages entirely if they have no content after filtering
|
|
527
|
+
*/
|
|
528
|
+
function sanitizeMessages(messages: MessageParam[]): MessageParam[] {
|
|
529
|
+
const result: MessageParam[] = [];
|
|
530
|
+
|
|
531
|
+
for (const message of messages) {
|
|
532
|
+
if (typeof message.content === 'string') {
|
|
533
|
+
// String content - keep only if non-empty
|
|
534
|
+
if (message.content.trim()) {
|
|
535
|
+
result.push(message);
|
|
536
|
+
}
|
|
537
|
+
continue;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
// Array content - filter out empty text blocks
|
|
541
|
+
const filteredContent = message.content.filter(block => {
|
|
542
|
+
if (block.type === 'text') {
|
|
543
|
+
return block.text && block.text.trim().length > 0;
|
|
544
|
+
}
|
|
545
|
+
// Keep all non-text blocks (tool_use, tool_result, image, etc.)
|
|
546
|
+
return true;
|
|
547
|
+
});
|
|
548
|
+
|
|
549
|
+
// Only include message if it has content after filtering
|
|
550
|
+
if (filteredContent.length > 0) {
|
|
551
|
+
result.push({
|
|
552
|
+
...message,
|
|
553
|
+
content: filteredContent
|
|
554
|
+
});
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
return result;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
/**
|
|
562
|
+
* Fix orphaned tool_use blocks in the conversation.
|
|
563
|
+
* @exported for testing
|
|
564
|
+
*
|
|
565
|
+
* When an agent is stopped mid-tool-execution, the assistant message contains tool_use blocks
|
|
566
|
+
* but no corresponding tool_result was added. The Anthropic API requires that every tool_use
|
|
567
|
+
* must be followed by a tool_result in the next user message.
|
|
568
|
+
*
|
|
569
|
+
* This function detects such cases and injects synthetic tool_result blocks indicating
|
|
570
|
+
* the tools were interrupted, allowing the conversation to continue.
|
|
571
|
+
*/
|
|
572
|
+
export function fixOrphanedToolUse(messages: MessageParam[]): MessageParam[] {
|
|
573
|
+
if (messages.length < 2) return messages;
|
|
574
|
+
|
|
575
|
+
const result: MessageParam[] = [];
|
|
576
|
+
|
|
577
|
+
for (let i = 0; i < messages.length; i++) {
|
|
578
|
+
const current = messages[i];
|
|
579
|
+
result.push(current);
|
|
580
|
+
|
|
581
|
+
// Check if this is an assistant message with tool_use blocks
|
|
582
|
+
if (current.role === 'assistant' && Array.isArray(current.content)) {
|
|
583
|
+
const toolUseBlocks = current.content.filter(
|
|
584
|
+
(block): block is ContentBlockParam & { type: 'tool_use'; id: string; name: string } =>
|
|
585
|
+
block.type === 'tool_use'
|
|
586
|
+
);
|
|
587
|
+
|
|
588
|
+
if (toolUseBlocks.length > 0) {
|
|
589
|
+
// Check if the next message is a user message with matching tool_results
|
|
590
|
+
const nextMessage = messages[i + 1];
|
|
591
|
+
|
|
592
|
+
if (nextMessage && nextMessage.role === 'user' && Array.isArray(nextMessage.content)) {
|
|
593
|
+
// Get tool_result IDs from the next message
|
|
594
|
+
const toolResultIds = new Set(
|
|
595
|
+
nextMessage.content
|
|
596
|
+
.filter((block): block is ToolResultBlockParam => block.type === 'tool_result')
|
|
597
|
+
.map(block => block.tool_use_id)
|
|
598
|
+
);
|
|
599
|
+
|
|
600
|
+
// Find orphaned tool_use blocks (no matching tool_result)
|
|
601
|
+
const orphanedToolUse = toolUseBlocks.filter(block => !toolResultIds.has(block.id));
|
|
602
|
+
|
|
603
|
+
if (orphanedToolUse.length > 0) {
|
|
604
|
+
// Inject synthetic tool_results for orphaned tool_use
|
|
605
|
+
const syntheticResults: ToolResultBlockParam[] = orphanedToolUse.map(block => ({
|
|
606
|
+
type: 'tool_result',
|
|
607
|
+
tool_use_id: block.id,
|
|
608
|
+
content: `[Tool interrupted: The user stopped the operation before "${block.name}" could execute.]`
|
|
609
|
+
}));
|
|
610
|
+
|
|
611
|
+
// Prepend synthetic results to the next user message
|
|
612
|
+
const updatedNextMessage: MessageParam = {
|
|
613
|
+
...nextMessage,
|
|
614
|
+
content: [...syntheticResults, ...nextMessage.content]
|
|
615
|
+
};
|
|
616
|
+
|
|
617
|
+
// Replace the next message in our iteration
|
|
618
|
+
messages[i + 1] = updatedNextMessage;
|
|
619
|
+
}
|
|
620
|
+
} else if (nextMessage && nextMessage.role === 'user') {
|
|
621
|
+
// Next message is a user message but not array content (plain text)
|
|
622
|
+
// We need to convert it and add tool_results
|
|
623
|
+
const syntheticResults: ToolResultBlockParam[] = toolUseBlocks.map(block => ({
|
|
624
|
+
type: 'tool_result',
|
|
625
|
+
tool_use_id: block.id,
|
|
626
|
+
content: `[Tool interrupted: The user stopped the operation before "${block.name}" could execute.]`
|
|
627
|
+
}));
|
|
628
|
+
|
|
629
|
+
const textContent: TextBlockParam = typeof nextMessage.content === 'string'
|
|
630
|
+
? { type: 'text', text: nextMessage.content }
|
|
631
|
+
: { type: 'text', text: '' };
|
|
632
|
+
|
|
633
|
+
const updatedNextMessage: MessageParam = {
|
|
634
|
+
role: 'user',
|
|
635
|
+
content: [...syntheticResults, textContent]
|
|
636
|
+
};
|
|
637
|
+
|
|
638
|
+
messages[i + 1] = updatedNextMessage;
|
|
639
|
+
}
|
|
640
|
+
// Note: If there's no nextMessage, we leave the conversation as-is.
|
|
641
|
+
// The tool_use blocks are expected to be there - the next turn will provide tool_results.
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
return result;
|
|
647
|
+
}
|
|
648
|
+
|
|
424
649
|
interface RequestOptions {
|
|
425
650
|
headers?: Record<string, string>;
|
|
426
651
|
}
|
|
@@ -440,8 +665,13 @@ function getClaudePayload(options: ExecutionOptions, prompt: ClaudePrompt): { pa
|
|
|
440
665
|
};
|
|
441
666
|
}
|
|
442
667
|
|
|
668
|
+
// Fix orphaned tool_use blocks (can occur when agent is stopped mid-tool-execution)
|
|
669
|
+
const fixedMessages = fixOrphanedToolUse(prompt.messages);
|
|
670
|
+
// Sanitize messages to remove empty text blocks (can occur from interrupted streaming)
|
|
671
|
+
const sanitizedMessages = sanitizeMessages(fixedMessages);
|
|
672
|
+
|
|
443
673
|
const payload = {
|
|
444
|
-
messages:
|
|
674
|
+
messages: sanitizedMessages,
|
|
445
675
|
system: prompt.system,
|
|
446
676
|
tools: options.tools, // we are using the same shape as claude for tools
|
|
447
677
|
temperature: model_options?.temperature,
|
|
@@ -1,16 +1,24 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Content, FinishReason, FunctionCallingConfigMode, FunctionDeclaration, GenerateContentConfig, GenerateContentParameters,
|
|
3
3
|
GenerateContentResponseUsageMetadata,
|
|
4
|
-
HarmBlockThreshold, HarmCategory, Modality, Part, SafetySetting, Schema, Tool, Type
|
|
4
|
+
HarmBlockThreshold, HarmCategory, Modality, Part, SafetySetting, Schema, ThinkingConfig, Tool, Type
|
|
5
5
|
} from "@google/genai";
|
|
6
6
|
import {
|
|
7
7
|
AIModel, Completion, CompletionChunkObject, CompletionResult, ExecutionOptions,
|
|
8
|
-
ExecutionTokenUsage,
|
|
9
|
-
|
|
8
|
+
ExecutionTokenUsage,
|
|
9
|
+
getConversationMeta,
|
|
10
|
+
getMaxTokensLimitVertexAi,
|
|
11
|
+
incrementConversationTurn,
|
|
12
|
+
JSONObject, JSONSchema, ModelType, PromptOptions, PromptRole,
|
|
13
|
+
PromptSegment, readStreamAsBase64, StatelessExecutionOptions,
|
|
14
|
+
stripBase64ImagesFromConversation,
|
|
15
|
+
ToolDefinition, ToolUse,
|
|
16
|
+
truncateLargeTextInConversation,
|
|
17
|
+
unwrapConversationArray,
|
|
10
18
|
VertexAIGeminiOptions
|
|
11
19
|
} from "@llumiverse/core";
|
|
12
20
|
import { asyncMap } from "@llumiverse/core/async";
|
|
13
|
-
import {
|
|
21
|
+
import { GenerateContentPrompt, VertexAIDriver } from "../index.js";
|
|
14
22
|
import { ModelDefinition } from "../models.js";
|
|
15
23
|
|
|
16
24
|
function supportsStructuredOutput(options: PromptOptions): boolean {
|
|
@@ -92,11 +100,7 @@ function getGeminiPayload(options: ExecutionOptions, prompt: GenerateContentProm
|
|
|
92
100
|
presencePenalty: model_options?.presence_penalty,
|
|
93
101
|
frequencyPenalty: model_options?.frequency_penalty,
|
|
94
102
|
seed: model_options?.seed,
|
|
95
|
-
thinkingConfig: thinkingConfigNeeded ?
|
|
96
|
-
{
|
|
97
|
-
includeThoughts: model_options?.include_thoughts ?? false,
|
|
98
|
-
thinkingBudget: geminiThinkingBudget(options),
|
|
99
|
-
} : undefined,
|
|
103
|
+
thinkingConfig: thinkingConfigNeeded ? geminiThinkingConfig(options) : undefined,
|
|
100
104
|
}
|
|
101
105
|
|
|
102
106
|
return {
|
|
@@ -471,11 +475,17 @@ function collectToolUseParts(content: Content): ToolUse[] | undefined {
|
|
|
471
475
|
const parts = content.parts ?? [];
|
|
472
476
|
for (const part of parts) {
|
|
473
477
|
if (part.functionCall) {
|
|
474
|
-
|
|
478
|
+
const toolUse: ToolUse = {
|
|
475
479
|
id: part.functionCall.name ?? '',
|
|
476
480
|
tool_name: part.functionCall.name ?? '',
|
|
477
481
|
tool_input: part.functionCall.args as JSONObject,
|
|
478
|
-
}
|
|
482
|
+
};
|
|
483
|
+
// Capture thought_signature for Gemini thinking models (2.5+/3.0+)
|
|
484
|
+
// This must be passed back with the function response
|
|
485
|
+
if (part.thoughtSignature) {
|
|
486
|
+
toolUse.thought_signature = part.thoughtSignature;
|
|
487
|
+
}
|
|
488
|
+
out.push(toolUse);
|
|
479
489
|
}
|
|
480
490
|
}
|
|
481
491
|
return out.length > 0 ? out : undefined;
|
|
@@ -545,6 +555,21 @@ function geminiThinkingBudget(option: StatelessExecutionOptions) {
|
|
|
545
555
|
return undefined;
|
|
546
556
|
}
|
|
547
557
|
|
|
558
|
+
function geminiThinkingConfig(option: StatelessExecutionOptions): ThinkingConfig | undefined {
|
|
559
|
+
const model_options = option.model_options as VertexAIGeminiOptions | undefined;
|
|
560
|
+
const include_thoughts = model_options?.include_thoughts ?? false;
|
|
561
|
+
if (model_options?.thinking_budget_tokens) {
|
|
562
|
+
return { includeThoughts: include_thoughts, thinkingBudget: model_options.thinking_budget_tokens };
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
// Set minimum thinking level by default.
|
|
566
|
+
// Docs: https://ai.google.dev/gemini-api/docs/thinking#set-budget
|
|
567
|
+
if (option.model.includes("gemini-2.5") || option.model.includes("gemini-3")) {
|
|
568
|
+
const thinking_budget_tokens = geminiThinkingBudget(option) ?? 0;
|
|
569
|
+
return { includeThoughts: include_thoughts, thinkingBudget: thinking_budget_tokens };
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
|
|
548
573
|
export class GeminiModelDefinition implements ModelDefinition<GenerateContentPrompt> {
|
|
549
574
|
|
|
550
575
|
model: AIModel
|
|
@@ -612,16 +637,18 @@ export class GeminiModelDefinition implements ModelDefinition<GenerateContentPro
|
|
|
612
637
|
if (!msg.tool_use_id) {
|
|
613
638
|
throw new Error("Tool response missing tool_use_id");
|
|
614
639
|
}
|
|
640
|
+
// Build functionResponse part with optional thought_signature for Gemini thinking models
|
|
641
|
+
const functionResponsePart: Part = {
|
|
642
|
+
functionResponse: {
|
|
643
|
+
name: msg.tool_use_id,
|
|
644
|
+
response: formatFunctionResponse(msg.content || ''),
|
|
645
|
+
},
|
|
646
|
+
// Include thought_signature if provided (required for Gemini 2.5+/3.0+ thinking models)
|
|
647
|
+
thoughtSignature: msg.thought_signature,
|
|
648
|
+
};
|
|
615
649
|
contents.push({
|
|
616
650
|
role: 'user',
|
|
617
|
-
parts: [
|
|
618
|
-
{
|
|
619
|
-
functionResponse: {
|
|
620
|
-
name: msg.tool_use_id,
|
|
621
|
-
response: formatFunctionResponse(msg.content || ''),
|
|
622
|
-
}
|
|
623
|
-
}
|
|
624
|
-
]
|
|
651
|
+
parts: [functionResponsePart]
|
|
625
652
|
});
|
|
626
653
|
} else { // PromptRole.user, PromptRole.assistant, PromptRole.safety
|
|
627
654
|
const parts: Part[] = [];
|
|
@@ -635,14 +662,27 @@ export class GeminiModelDefinition implements ModelDefinition<GenerateContentPro
|
|
|
635
662
|
// File content handling
|
|
636
663
|
if (msg.files) {
|
|
637
664
|
for (const f of msg.files) {
|
|
638
|
-
|
|
639
|
-
const
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
665
|
+
let fileUrl = await f.getURL();
|
|
666
|
+
const isGsUrl = fileUrl.startsWith('gs://') || fileUrl.startsWith('https://storage.googleapis.com/');
|
|
667
|
+
|
|
668
|
+
if (isGsUrl) {
|
|
669
|
+
parts.push({
|
|
670
|
+
fileData: {
|
|
671
|
+
fileUri: fileUrl,
|
|
672
|
+
mimeType: f.mime_type
|
|
673
|
+
}
|
|
674
|
+
});
|
|
675
|
+
} else {
|
|
676
|
+
// Inline data handling
|
|
677
|
+
const stream = await f.getStream();
|
|
678
|
+
const data = await readStreamAsBase64(stream);
|
|
679
|
+
parts.push({
|
|
680
|
+
inlineData: {
|
|
681
|
+
data,
|
|
682
|
+
mimeType: f.mime_type
|
|
683
|
+
}
|
|
684
|
+
});
|
|
685
|
+
}
|
|
646
686
|
}
|
|
647
687
|
}
|
|
648
688
|
|
|
@@ -731,9 +771,10 @@ export class GeminiModelDefinition implements ModelDefinition<GenerateContentPro
|
|
|
731
771
|
const modelName = splits[splits.length - 1];
|
|
732
772
|
options = { ...options, model: modelName };
|
|
733
773
|
|
|
734
|
-
let conversation = updateConversation(options.conversation
|
|
774
|
+
let conversation = updateConversation(options.conversation, prompt.contents);
|
|
735
775
|
prompt.contents = conversation;
|
|
736
776
|
|
|
777
|
+
// TODO: Remove hack, use global endpoint manually if needed.
|
|
737
778
|
if (options.model.includes("gemini-2.5-flash-image")) {
|
|
738
779
|
region = "global"; // Gemini Flash Image only available in global region, this is for nano-banana model
|
|
739
780
|
}
|
|
@@ -780,12 +821,27 @@ export class GeminiModelDefinition implements ModelDefinition<GenerateContentPro
|
|
|
780
821
|
finish_reason = "tool_use";
|
|
781
822
|
}
|
|
782
823
|
|
|
824
|
+
// Increment turn counter for deferred stripping
|
|
825
|
+
conversation = incrementConversationTurn(conversation) as Content[];
|
|
826
|
+
|
|
827
|
+
// Strip large base64 image data based on options.stripImagesAfterTurns
|
|
828
|
+
const currentTurn = getConversationMeta(conversation).turnNumber;
|
|
829
|
+
const stripOptions = {
|
|
830
|
+
keepForTurns: options.stripImagesAfterTurns ?? Infinity,
|
|
831
|
+
currentTurn,
|
|
832
|
+
textMaxTokens: options.stripTextMaxTokens
|
|
833
|
+
};
|
|
834
|
+
let processedConversation = stripBase64ImagesFromConversation(conversation, stripOptions);
|
|
835
|
+
|
|
836
|
+
// Truncate large text content if configured
|
|
837
|
+
processedConversation = truncateLargeTextInConversation(processedConversation, stripOptions);
|
|
838
|
+
|
|
783
839
|
return {
|
|
784
840
|
result: result && result.length > 0 ? result : [{ type: "text" as const, value: '' }],
|
|
785
841
|
token_usage: token_usage,
|
|
786
842
|
finish_reason: finish_reason,
|
|
787
843
|
original_response: options.include_original_response ? response : undefined,
|
|
788
|
-
conversation,
|
|
844
|
+
conversation: processedConversation,
|
|
789
845
|
tool_use
|
|
790
846
|
} satisfies Completion;
|
|
791
847
|
}
|
|
@@ -799,6 +855,10 @@ export class GeminiModelDefinition implements ModelDefinition<GenerateContentPro
|
|
|
799
855
|
const modelName = splits[splits.length - 1];
|
|
800
856
|
options = { ...options, model: modelName };
|
|
801
857
|
|
|
858
|
+
// Include conversation history in prompt contents (same as non-streaming)
|
|
859
|
+
const conversation = updateConversation(options.conversation, prompt.contents);
|
|
860
|
+
prompt.contents = conversation;
|
|
861
|
+
|
|
802
862
|
if (options.model.includes("gemini-2.5-flash-image")) {
|
|
803
863
|
region = "global"; // Gemini Flash Image only available in global region, this is for nano-banana model
|
|
804
864
|
}
|
|
@@ -885,16 +945,19 @@ function getToolFunction(tool: ToolDefinition): FunctionDeclaration {
|
|
|
885
945
|
};
|
|
886
946
|
}
|
|
887
947
|
|
|
888
|
-
|
|
889
948
|
/**
|
|
890
949
|
* Update the conversation messages
|
|
891
950
|
* @param prompt
|
|
892
951
|
* @param response
|
|
893
952
|
* @returns
|
|
894
953
|
*/
|
|
895
|
-
function updateConversation(conversation:
|
|
896
|
-
|
|
954
|
+
function updateConversation(conversation: unknown, prompt: Content[]): Content[] {
|
|
955
|
+
// Unwrap array if wrapped, otherwise treat as array
|
|
956
|
+
const unwrapped = unwrapConversationArray<Content>(conversation);
|
|
957
|
+
const convArray = unwrapped ?? (conversation as Content[] || []);
|
|
958
|
+
return convArray.concat(prompt);
|
|
897
959
|
}
|
|
960
|
+
|
|
898
961
|
/**
|
|
899
962
|
*
|
|
900
963
|
* Gemini supports JSON output in the response. so we test if the response is a valid JSON object. otherwise we treat the response as a string.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
-
AIModel, Completion, ExecutionOptions,
|
|
2
|
+
AIModel, Completion, ExecutionOptions,
|
|
3
3
|
ModelType, PromptRole, PromptSegment, readStreamAsBase64, ImagenOptions
|
|
4
4
|
} from "@llumiverse/core";
|
|
5
5
|
import { VertexAIDriver } from "../index.js";
|
|
@@ -328,10 +328,6 @@ export class ImagenModelDefinition {
|
|
|
328
328
|
}
|
|
329
329
|
options.model_options = options.model_options as ImagenOptions | undefined;
|
|
330
330
|
|
|
331
|
-
if (options.output_modality !== Modalities.image) {
|
|
332
|
-
throw new Error(`Image generation requires image output_modality`);
|
|
333
|
-
}
|
|
334
|
-
|
|
335
331
|
const taskType: string = options.model_options?.edit_mode ?? ImagenTaskType.TEXT_IMAGE;
|
|
336
332
|
|
|
337
333
|
driver.logger.info("Task type: " + taskType);
|
package/src/xai/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AIModel,
|
|
1
|
+
import { AIModel, DriverOptions, PromptOptions, PromptSegment, Providers } from "@llumiverse/core";
|
|
2
2
|
import { formatOpenAILikeMultimodalPrompt, OpenAIPromptFormatterOptions } from "../openai/openai_format.js";
|
|
3
3
|
import { FetchClient } from "@vertesia/api-fetch-client";
|
|
4
4
|
import OpenAI from "openai";
|
|
@@ -15,7 +15,7 @@ export interface xAiDriverOptions extends DriverOptions {
|
|
|
15
15
|
export class xAIDriver extends BaseOpenAIDriver {
|
|
16
16
|
|
|
17
17
|
service: OpenAI;
|
|
18
|
-
provider
|
|
18
|
+
readonly provider = Providers.xai;
|
|
19
19
|
xai_service: FetchClient;
|
|
20
20
|
DEFAULT_ENDPOINT = "https://api.x.ai/v1";
|
|
21
21
|
|
|
@@ -31,7 +31,6 @@ export class xAIDriver extends BaseOpenAIDriver {
|
|
|
31
31
|
baseURL: opts.endpoint ?? this.DEFAULT_ENDPOINT,
|
|
32
32
|
});
|
|
33
33
|
this.xai_service = new FetchClient(opts.endpoint ?? this.DEFAULT_ENDPOINT).withAuthCallback(async () => `Bearer ${opts.apiKey}`);
|
|
34
|
-
this.provider = "xai";
|
|
35
34
|
//this.formatPrompt = this._formatPrompt; //TODO: fix xai prompt formatting
|
|
36
35
|
}
|
|
37
36
|
|
|
@@ -49,17 +48,9 @@ export class xAIDriver extends BaseOpenAIDriver {
|
|
|
49
48
|
|
|
50
49
|
}
|
|
51
50
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
finish_reason: result.choices[0].finish_reason,
|
|
56
|
-
token_usage: {
|
|
57
|
-
prompt: result.usage?.prompt_tokens,
|
|
58
|
-
result: result.usage?.completion_tokens,
|
|
59
|
-
total: result.usage?.total_tokens,
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
51
|
+
// Note: We intentionally do NOT override extractDataFromResponse here.
|
|
52
|
+
// The base class implementation properly handles tool_calls extraction.
|
|
53
|
+
// xAI's API is OpenAI-compatible and returns tool_calls in the same format.
|
|
63
54
|
|
|
64
55
|
async listModels(): Promise<AIModel[]> {
|
|
65
56
|
const [lm, em] = await Promise.all([
|
|
@@ -76,10 +67,12 @@ export class xAIDriver extends BaseOpenAIDriver {
|
|
|
76
67
|
return {
|
|
77
68
|
id: model.id,
|
|
78
69
|
provider: this.provider,
|
|
79
|
-
name: model.
|
|
80
|
-
description: model.
|
|
70
|
+
name: model.id,
|
|
71
|
+
description: `${model.id} by ${model.owned_by}`,
|
|
81
72
|
is_multimodal: model.input_modalities.length > 1,
|
|
82
|
-
|
|
73
|
+
input_modalities: model.input_modalities,
|
|
74
|
+
output_modalities: model.output_modalities,
|
|
75
|
+
tags: [...model.input_modalities.map(m => `i:${m}`), ...model.output_modalities.map(m => `o:${m}`)],
|
|
83
76
|
} satisfies AIModel;
|
|
84
77
|
});
|
|
85
78
|
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.TestErrorCompletionStream = void 0;
|
|
4
|
-
const utils_js_1 = require("./utils.js");
|
|
5
|
-
class TestErrorCompletionStream {
|
|
6
|
-
segments;
|
|
7
|
-
options;
|
|
8
|
-
completion;
|
|
9
|
-
constructor(segments, options) {
|
|
10
|
-
this.segments = segments;
|
|
11
|
-
this.options = options;
|
|
12
|
-
}
|
|
13
|
-
async *[Symbol.asyncIterator]() {
|
|
14
|
-
yield "Started TestError. Next we will thrown an error.\n";
|
|
15
|
-
(0, utils_js_1.sleep)(1000);
|
|
16
|
-
(0, utils_js_1.throwError)("Testing stream completion error.", this.segments);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
exports.TestErrorCompletionStream = TestErrorCompletionStream;
|
|
20
|
-
//# sourceMappingURL=TestErrorCompletionStream.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"TestErrorCompletionStream.js","sourceRoot":"","sources":["../../../src/test/TestErrorCompletionStream.ts"],"names":[],"mappings":";;;AACA,yCAA+C;AAE/C,MAAa,yBAAyB;IAIf;IACR;IAHX,UAAU,CAAiD;IAE3D,YAAmB,QAAyB,EACjC,OAAyB;QADjB,aAAQ,GAAR,QAAQ,CAAiB;QACjC,YAAO,GAAP,OAAO,CAAkB;IACpC,CAAC;IACD,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC;QACzB,MAAM,oDAAoD,CAAC;QAC3D,IAAA,gBAAK,EAAC,IAAI,CAAC,CAAC;QACZ,IAAA,qBAAU,EAAC,kCAAkC,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IAClE,CAAC;CACJ;AAZD,8DAYC"}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.TestValidationErrorCompletionStream = void 0;
|
|
4
|
-
const utils_js_1 = require("./utils.js");
|
|
5
|
-
class TestValidationErrorCompletionStream {
|
|
6
|
-
segments;
|
|
7
|
-
options;
|
|
8
|
-
completion;
|
|
9
|
-
constructor(segments, options) {
|
|
10
|
-
this.segments = segments;
|
|
11
|
-
this.options = options;
|
|
12
|
-
}
|
|
13
|
-
async *[Symbol.asyncIterator]() {
|
|
14
|
-
yield "Started TestValidationError.\n";
|
|
15
|
-
await (0, utils_js_1.sleep)(1000);
|
|
16
|
-
yield "chunk1\n";
|
|
17
|
-
await (0, utils_js_1.sleep)(1000);
|
|
18
|
-
yield "chunk2\n";
|
|
19
|
-
await (0, utils_js_1.sleep)(1000);
|
|
20
|
-
this.completion = (0, utils_js_1.createValidationErrorCompletion)(this.segments);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
exports.TestValidationErrorCompletionStream = TestValidationErrorCompletionStream;
|
|
24
|
-
//# sourceMappingURL=TestValidationErrorCompletionStream.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"TestValidationErrorCompletionStream.js","sourceRoot":"","sources":["../../../src/test/TestValidationErrorCompletionStream.ts"],"names":[],"mappings":";;;AACA,yCAAoE;AAGpE,MAAa,mCAAmC;IAIzB;IACR;IAHX,UAAU,CAAiD;IAE3D,YAAmB,QAAyB,EACjC,OAAyB;QADjB,aAAQ,GAAR,QAAQ,CAAiB;QACjC,YAAO,GAAP,OAAO,CAAkB;IACpC,CAAC;IACD,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC;QACzB,MAAM,gCAAgC,CAAC;QACvC,MAAM,IAAA,gBAAK,EAAC,IAAI,CAAC,CAAC;QAClB,MAAM,UAAU,CAAC;QACjB,MAAM,IAAA,gBAAK,EAAC,IAAI,CAAC,CAAC;QAClB,MAAM,UAAU,CAAC;QACjB,MAAM,IAAA,gBAAK,EAAC,IAAI,CAAC,CAAC;QAClB,IAAI,CAAC,UAAU,GAAG,IAAA,0CAA+B,EAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACrE,CAAC;CACJ;AAhBD,kFAgBC"}
|