@juspay/neurolink 10.10.12 → 10.11.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/CHANGELOG.md +6 -0
- package/dist/adapters/imageFormatSupport.d.ts +75 -0
- package/dist/adapters/imageFormatSupport.js +283 -0
- package/dist/adapters/video/ffmpegAdapter.d.ts +6 -0
- package/dist/adapters/video/ffmpegAdapter.js +1 -1
- package/dist/browser/neurolink.min.js +399 -398
- package/dist/lib/adapters/imageFormatSupport.d.ts +75 -0
- package/dist/lib/adapters/imageFormatSupport.js +284 -0
- package/dist/lib/adapters/video/ffmpegAdapter.d.ts +6 -0
- package/dist/lib/adapters/video/ffmpegAdapter.js +1 -1
- package/dist/lib/processors/config/fileExtensions.d.ts +32 -15
- package/dist/lib/processors/config/fileExtensions.js +27 -66
- package/dist/lib/processors/config/fileTypeRegistry.d.ts +106 -0
- package/dist/lib/processors/config/fileTypeRegistry.js +702 -0
- package/dist/lib/processors/config/index.d.ts +2 -1
- package/dist/lib/processors/config/index.js +5 -1
- package/dist/lib/processors/config/mimeConstants.d.ts +22 -7
- package/dist/lib/processors/config/mimeConstants.js +45 -66
- package/dist/lib/processors/media/AudioProcessor.js +16 -38
- package/dist/lib/processors/media/VideoProcessor.js +11 -32
- package/dist/lib/providers/googleAiStudio/client.js +12 -1
- package/dist/lib/providers/googleVertex/client.js +123 -66
- package/dist/lib/types/file.d.ts +41 -0
- package/dist/lib/utils/fileDetector.js +367 -251
- package/dist/lib/utils/imageProcessor.js +14 -17
- package/dist/lib/utils/markupSniff.d.ts +37 -0
- package/dist/lib/utils/markupSniff.js +125 -0
- package/dist/lib/utils/messageBuilder.d.ts +14 -0
- package/dist/lib/utils/messageBuilder.js +172 -92
- package/dist/processors/config/fileExtensions.d.ts +32 -15
- package/dist/processors/config/fileExtensions.js +27 -66
- package/dist/processors/config/fileTypeRegistry.d.ts +106 -0
- package/dist/processors/config/fileTypeRegistry.js +701 -0
- package/dist/processors/config/index.d.ts +2 -1
- package/dist/processors/config/index.js +5 -1
- package/dist/processors/config/mimeConstants.d.ts +22 -7
- package/dist/processors/config/mimeConstants.js +45 -66
- package/dist/processors/media/AudioProcessor.js +16 -38
- package/dist/processors/media/VideoProcessor.js +11 -32
- package/dist/providers/googleAiStudio/client.js +12 -1
- package/dist/providers/googleVertex/client.js +123 -66
- package/dist/types/file.d.ts +41 -0
- package/dist/utils/fileDetector.js +367 -251
- package/dist/utils/imageProcessor.js +14 -17
- package/dist/utils/markupSniff.d.ts +37 -0
- package/dist/utils/markupSniff.js +124 -0
- package/dist/utils/messageBuilder.d.ts +14 -0
- package/dist/utils/messageBuilder.js +172 -92
- package/package.json +3 -2
|
@@ -5,16 +5,18 @@ import path from "path";
|
|
|
5
5
|
import os from "os";
|
|
6
6
|
import { AIProviderName, ErrorCategory, ErrorSeverity, } from "../../constants/enums.js";
|
|
7
7
|
import { BaseProvider } from "../../core/baseProvider.js";
|
|
8
|
+
import { unwrapImagePayload } from "../../adapters/imageFormatSupport.js";
|
|
9
|
+
import { getMimeTypeForExtension } from "../../processors/config/mimeConstants.js";
|
|
8
10
|
import { DEFAULT_GEMINI_STREAM_TIMEOUT_MS, DEFAULT_MAX_STEPS, DEFAULT_TOOL_EXECUTION_TIMEOUT_MS, DEFAULT_TOOL_MAX_RETRIES, GLOBAL_LOCATION_MODELS, IMAGE_GENERATION_MODELS, TOOL_STORAGE_TIMEOUT_MS, } from "../../core/constants.js";
|
|
9
11
|
import { ModelConfigurationManager } from "../../core/modelConfiguration.js";
|
|
10
12
|
import { isSchemaComplexityError } from "../../core/modules/structuredOutputPolicy.js";
|
|
11
|
-
import { stringifyContentSafe } from "../../utils/logSanitize.js";
|
|
13
|
+
import { redactUrlForError, stringifyContentSafe, } from "../../utils/logSanitize.js";
|
|
12
14
|
import { createProxyFetch } from "../../proxy/proxyFetch.js";
|
|
13
15
|
import { AuthenticationError, InvalidModelError, NetworkError, ProviderError, RateLimitError, } from "../../types/index.js";
|
|
14
16
|
import { ERROR_CODES, NeuroLinkError } from "../../utils/errorHandling.js";
|
|
15
17
|
import { applyVertexAnthropicCacheBreakpoints } from "../../utils/anthropicCacheBreakpoints.js";
|
|
16
18
|
import { FileDetector } from "../../utils/fileDetector.js";
|
|
17
|
-
import { mergeMediaFileAliases, processUnifiedFilesArray, } from "../../utils/messageBuilder.js";
|
|
19
|
+
import { mergeMediaFileAliases, normalizeVisionImageFormats, processUnifiedFilesArray, } from "../../utils/messageBuilder.js";
|
|
18
20
|
import { logger } from "../../utils/logger.js";
|
|
19
21
|
import { GEMINI_ELISION_NOTE, planGeminiLoopReclaim, previewGeminiToolResponseText, } from "../../context/geminiLoopGuard.js";
|
|
20
22
|
import { ANTHROPIC_ELISION_NOTE, planAnthropicLoopReclaim, previewAnthropicToolResultText, } from "../../context/anthropicLoopGuard.js";
|
|
@@ -1035,16 +1037,19 @@ export class GoogleVertexProvider extends BaseProvider {
|
|
|
1035
1037
|
if (options.input) {
|
|
1036
1038
|
mergeMediaFileAliases(options.input);
|
|
1037
1039
|
}
|
|
1038
|
-
if (
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
logger.warn(`[GoogleVertex] processUnifiedFilesArray threw, continuing without file content: ${fileError instanceof Error ? fileError.message : String(fileError)}`);
|
|
1040
|
+
if (options.input?.files?.length) {
|
|
1041
|
+
try {
|
|
1042
|
+
// Mutates options.input.text / .images / .pdfFiles in place.
|
|
1043
|
+
await processUnifiedFilesArray(options, 100 * 1024 * 1024, this.providerName);
|
|
1044
|
+
}
|
|
1045
|
+
catch (fileError) {
|
|
1046
|
+
logger.warn(`[GoogleVertex] processUnifiedFilesArray threw, continuing without file content: ${fileError instanceof Error ? fileError.message : String(fileError)}`);
|
|
1047
|
+
}
|
|
1047
1048
|
}
|
|
1049
|
+
// Runs even without input.files: a caller can populate input.images
|
|
1050
|
+
// directly, and this native path never reaches the shared multimodal
|
|
1051
|
+
// builder that would otherwise normalize the formats.
|
|
1052
|
+
await normalizeVisionImageFormats(options.input);
|
|
1048
1053
|
}
|
|
1049
1054
|
async executeStream(options, _analysisSchema) {
|
|
1050
1055
|
// ALL models now use native SDKs - no more @ai-sdk/google-vertex dependency
|
|
@@ -1401,23 +1406,31 @@ export class GoogleVertexProvider extends BaseProvider {
|
|
|
1401
1406
|
// Add images as inlineData parts if present
|
|
1402
1407
|
if (multimodalInput?.images && multimodalInput.images.length > 0) {
|
|
1403
1408
|
logger.debug(`[GoogleVertex] Processing ${multimodalInput.images.length} image(s) for native stream`);
|
|
1404
|
-
for (const
|
|
1409
|
+
for (const rawImage of multimodalInput.images) {
|
|
1410
|
+
// `input.images` accepts `{ data, altText }` as a documented public
|
|
1411
|
+
// shape, but this loop only ever handled Buffer | string — a wrapper
|
|
1412
|
+
// fell through to the "assume raw bytes" branch and base64-encoded the
|
|
1413
|
+
// OBJECT, sending the literal "[object Object]" to Vertex. Unwrap once,
|
|
1414
|
+
// here, so every branch below sees the payload it expects.
|
|
1415
|
+
const image = unwrapImagePayload(rawImage);
|
|
1405
1416
|
let imageBuffer;
|
|
1406
1417
|
let mimeType = "image/jpeg"; // Default
|
|
1407
1418
|
if (typeof image === "string") {
|
|
1408
1419
|
if (fs.existsSync(image)) {
|
|
1409
1420
|
imageBuffer = fs.readFileSync(image);
|
|
1410
1421
|
// Detect mime type from extension
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1422
|
+
// Registry lookup rather than a png/gif/webp switch defaulting to
|
|
1423
|
+
// JPEG: that default labelled a .heic/.bmp/.tiff/.avif reference
|
|
1424
|
+
// image as image/jpeg, which is simply untrue and is what Vertex
|
|
1425
|
+
// then rejected. The registry answers "application/octet-stream"
|
|
1426
|
+
// for a missing or unregistered extension though, and Vertex
|
|
1427
|
+
// rejects a non-image media type just as firmly — so fall back to
|
|
1428
|
+
// the bytes, which are already in hand, rather than sending either
|
|
1429
|
+
// a guess or a non-image type.
|
|
1430
|
+
const byExtension = getMimeTypeForExtension(image);
|
|
1431
|
+
mimeType = byExtension.startsWith("image/")
|
|
1432
|
+
? byExtension
|
|
1433
|
+
: this.detectImageType(imageBuffer);
|
|
1421
1434
|
}
|
|
1422
1435
|
else if (image.startsWith("data:")) {
|
|
1423
1436
|
// Handle data URL
|
|
@@ -1438,7 +1451,9 @@ export class GoogleVertexProvider extends BaseProvider {
|
|
|
1438
1451
|
try {
|
|
1439
1452
|
const response = await fetch(image);
|
|
1440
1453
|
if (!response.ok) {
|
|
1441
|
-
|
|
1454
|
+
// The URL may be presigned or carry credentials in its query
|
|
1455
|
+
// string, and wrapper URLs now reach this branch too.
|
|
1456
|
+
logger.warn(`[GoogleVertex] Image fetch failed: ${response.status} ${response.statusText}, skipping`, { url: redactUrlForError(image) });
|
|
1442
1457
|
continue;
|
|
1443
1458
|
}
|
|
1444
1459
|
const arrayBuffer = await response.arrayBuffer();
|
|
@@ -1449,7 +1464,7 @@ export class GoogleVertexProvider extends BaseProvider {
|
|
|
1449
1464
|
}
|
|
1450
1465
|
}
|
|
1451
1466
|
catch (fetchError) {
|
|
1452
|
-
logger.warn(`[GoogleVertex] Image URL fetch threw, skipping: ${fetchError instanceof Error ? fetchError.message : String(fetchError)}`, { url: image });
|
|
1467
|
+
logger.warn(`[GoogleVertex] Image URL fetch threw, skipping: ${fetchError instanceof Error ? fetchError.message : String(fetchError)}`, { url: redactUrlForError(image) });
|
|
1453
1468
|
continue;
|
|
1454
1469
|
}
|
|
1455
1470
|
}
|
|
@@ -2396,23 +2411,31 @@ export class GoogleVertexProvider extends BaseProvider {
|
|
|
2396
2411
|
// Add images as inlineData parts if present
|
|
2397
2412
|
if (multimodalInput?.images && multimodalInput.images.length > 0) {
|
|
2398
2413
|
logger.debug(`[GoogleVertex] Processing ${multimodalInput.images.length} image(s) for native generate`);
|
|
2399
|
-
for (const
|
|
2414
|
+
for (const rawImage of multimodalInput.images) {
|
|
2415
|
+
// `input.images` accepts `{ data, altText }` as a documented public
|
|
2416
|
+
// shape, but this loop only ever handled Buffer | string — a wrapper
|
|
2417
|
+
// fell through to the "assume raw bytes" branch and base64-encoded the
|
|
2418
|
+
// OBJECT, sending the literal "[object Object]" to Vertex. Unwrap once,
|
|
2419
|
+
// here, so every branch below sees the payload it expects.
|
|
2420
|
+
const image = unwrapImagePayload(rawImage);
|
|
2400
2421
|
let imageBuffer;
|
|
2401
2422
|
let mimeType = "image/jpeg"; // Default
|
|
2402
2423
|
if (typeof image === "string") {
|
|
2403
2424
|
if (fs.existsSync(image)) {
|
|
2404
2425
|
imageBuffer = fs.readFileSync(image);
|
|
2405
2426
|
// Detect mime type from extension
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2427
|
+
// Registry lookup rather than a png/gif/webp switch defaulting to
|
|
2428
|
+
// JPEG: that default labelled a .heic/.bmp/.tiff/.avif reference
|
|
2429
|
+
// image as image/jpeg, which is simply untrue and is what Vertex
|
|
2430
|
+
// then rejected. The registry answers "application/octet-stream"
|
|
2431
|
+
// for a missing or unregistered extension though, and Vertex
|
|
2432
|
+
// rejects a non-image media type just as firmly — so fall back to
|
|
2433
|
+
// the bytes, which are already in hand, rather than sending either
|
|
2434
|
+
// a guess or a non-image type.
|
|
2435
|
+
const byExtension = getMimeTypeForExtension(image);
|
|
2436
|
+
mimeType = byExtension.startsWith("image/")
|
|
2437
|
+
? byExtension
|
|
2438
|
+
: this.detectImageType(imageBuffer);
|
|
2416
2439
|
}
|
|
2417
2440
|
else if (image.startsWith("data:")) {
|
|
2418
2441
|
// Handle data URL
|
|
@@ -2433,7 +2456,9 @@ export class GoogleVertexProvider extends BaseProvider {
|
|
|
2433
2456
|
try {
|
|
2434
2457
|
const response = await fetch(image);
|
|
2435
2458
|
if (!response.ok) {
|
|
2436
|
-
|
|
2459
|
+
// The URL may be presigned or carry credentials in its query
|
|
2460
|
+
// string, and wrapper URLs now reach this branch too.
|
|
2461
|
+
logger.warn(`[GoogleVertex] Image fetch failed: ${response.status} ${response.statusText}, skipping`, { url: redactUrlForError(image) });
|
|
2437
2462
|
continue;
|
|
2438
2463
|
}
|
|
2439
2464
|
const arrayBuffer = await response.arrayBuffer();
|
|
@@ -2444,7 +2469,7 @@ export class GoogleVertexProvider extends BaseProvider {
|
|
|
2444
2469
|
}
|
|
2445
2470
|
}
|
|
2446
2471
|
catch (fetchError) {
|
|
2447
|
-
logger.warn(`[GoogleVertex] Image URL fetch threw, skipping: ${fetchError instanceof Error ? fetchError.message : String(fetchError)}`, { url: image });
|
|
2472
|
+
logger.warn(`[GoogleVertex] Image URL fetch threw, skipping: ${fetchError instanceof Error ? fetchError.message : String(fetchError)}`, { url: redactUrlForError(image) });
|
|
2448
2473
|
continue;
|
|
2449
2474
|
}
|
|
2450
2475
|
}
|
|
@@ -3497,23 +3522,31 @@ export class GoogleVertexProvider extends BaseProvider {
|
|
|
3497
3522
|
// Add images as image parts if present
|
|
3498
3523
|
if (multimodalInput?.images && multimodalInput.images.length > 0) {
|
|
3499
3524
|
logger.debug(`[GoogleVertex] Processing ${multimodalInput.images.length} image(s) for native Anthropic stream`);
|
|
3500
|
-
for (const
|
|
3525
|
+
for (const rawImage of multimodalInput.images) {
|
|
3526
|
+
// `input.images` accepts `{ data, altText }` as a documented public
|
|
3527
|
+
// shape, but this loop only ever handled Buffer | string — a wrapper
|
|
3528
|
+
// fell through to the "assume raw bytes" branch and base64-encoded the
|
|
3529
|
+
// OBJECT, sending the literal "[object Object]" to Vertex. Unwrap once,
|
|
3530
|
+
// here, so every branch below sees the payload it expects.
|
|
3531
|
+
const image = unwrapImagePayload(rawImage);
|
|
3501
3532
|
let imageBuffer;
|
|
3502
3533
|
let mimeType = "image/jpeg"; // Default
|
|
3503
3534
|
if (typeof image === "string") {
|
|
3504
3535
|
if (fs.existsSync(image)) {
|
|
3505
3536
|
imageBuffer = fs.readFileSync(image);
|
|
3506
3537
|
// Detect mime type from extension
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
3538
|
+
// Registry lookup rather than a png/gif/webp switch defaulting to
|
|
3539
|
+
// JPEG: that default labelled a .heic/.bmp/.tiff/.avif reference
|
|
3540
|
+
// image as image/jpeg, which is simply untrue and is what Vertex
|
|
3541
|
+
// then rejected. The registry answers "application/octet-stream"
|
|
3542
|
+
// for a missing or unregistered extension though, and Vertex
|
|
3543
|
+
// rejects a non-image media type just as firmly — so fall back to
|
|
3544
|
+
// the bytes, which are already in hand, rather than sending either
|
|
3545
|
+
// a guess or a non-image type.
|
|
3546
|
+
const byExtension = getMimeTypeForExtension(image);
|
|
3547
|
+
mimeType = byExtension.startsWith("image/")
|
|
3548
|
+
? byExtension
|
|
3549
|
+
: this.detectImageType(imageBuffer);
|
|
3517
3550
|
}
|
|
3518
3551
|
else if (image.startsWith("data:")) {
|
|
3519
3552
|
// Handle data URL
|
|
@@ -3534,7 +3567,9 @@ export class GoogleVertexProvider extends BaseProvider {
|
|
|
3534
3567
|
try {
|
|
3535
3568
|
const response = await fetch(image);
|
|
3536
3569
|
if (!response.ok) {
|
|
3537
|
-
|
|
3570
|
+
// The URL may be presigned or carry credentials in its query
|
|
3571
|
+
// string, and wrapper URLs now reach this branch too.
|
|
3572
|
+
logger.warn(`[GoogleVertex] Image fetch failed: ${response.status} ${response.statusText}, skipping`, { url: redactUrlForError(image) });
|
|
3538
3573
|
continue;
|
|
3539
3574
|
}
|
|
3540
3575
|
const arrayBuffer = await response.arrayBuffer();
|
|
@@ -3545,7 +3580,7 @@ export class GoogleVertexProvider extends BaseProvider {
|
|
|
3545
3580
|
}
|
|
3546
3581
|
}
|
|
3547
3582
|
catch (fetchError) {
|
|
3548
|
-
logger.warn(`[GoogleVertex] Image URL fetch threw, skipping: ${fetchError instanceof Error ? fetchError.message : String(fetchError)}`, { url: image });
|
|
3583
|
+
logger.warn(`[GoogleVertex] Image URL fetch threw, skipping: ${fetchError instanceof Error ? fetchError.message : String(fetchError)}`, { url: redactUrlForError(image) });
|
|
3549
3584
|
continue;
|
|
3550
3585
|
}
|
|
3551
3586
|
}
|
|
@@ -4832,23 +4867,31 @@ export class GoogleVertexProvider extends BaseProvider {
|
|
|
4832
4867
|
// Add images as image parts if present
|
|
4833
4868
|
if (multimodalInput?.images && multimodalInput.images.length > 0) {
|
|
4834
4869
|
logger.debug(`[GoogleVertex] Processing ${multimodalInput.images.length} image(s) for native Anthropic generate`);
|
|
4835
|
-
for (const
|
|
4870
|
+
for (const rawImage of multimodalInput.images) {
|
|
4871
|
+
// `input.images` accepts `{ data, altText }` as a documented public
|
|
4872
|
+
// shape, but this loop only ever handled Buffer | string — a wrapper
|
|
4873
|
+
// fell through to the "assume raw bytes" branch and base64-encoded the
|
|
4874
|
+
// OBJECT, sending the literal "[object Object]" to Vertex. Unwrap once,
|
|
4875
|
+
// here, so every branch below sees the payload it expects.
|
|
4876
|
+
const image = unwrapImagePayload(rawImage);
|
|
4836
4877
|
let imageBuffer;
|
|
4837
4878
|
let mimeType = "image/jpeg"; // Default
|
|
4838
4879
|
if (typeof image === "string") {
|
|
4839
4880
|
if (fs.existsSync(image)) {
|
|
4840
4881
|
imageBuffer = fs.readFileSync(image);
|
|
4841
4882
|
// Detect mime type from extension
|
|
4842
|
-
|
|
4843
|
-
|
|
4844
|
-
|
|
4845
|
-
|
|
4846
|
-
|
|
4847
|
-
|
|
4848
|
-
|
|
4849
|
-
|
|
4850
|
-
|
|
4851
|
-
|
|
4883
|
+
// Registry lookup rather than a png/gif/webp switch defaulting to
|
|
4884
|
+
// JPEG: that default labelled a .heic/.bmp/.tiff/.avif reference
|
|
4885
|
+
// image as image/jpeg, which is simply untrue and is what Vertex
|
|
4886
|
+
// then rejected. The registry answers "application/octet-stream"
|
|
4887
|
+
// for a missing or unregistered extension though, and Vertex
|
|
4888
|
+
// rejects a non-image media type just as firmly — so fall back to
|
|
4889
|
+
// the bytes, which are already in hand, rather than sending either
|
|
4890
|
+
// a guess or a non-image type.
|
|
4891
|
+
const byExtension = getMimeTypeForExtension(image);
|
|
4892
|
+
mimeType = byExtension.startsWith("image/")
|
|
4893
|
+
? byExtension
|
|
4894
|
+
: this.detectImageType(imageBuffer);
|
|
4852
4895
|
}
|
|
4853
4896
|
else if (image.startsWith("data:")) {
|
|
4854
4897
|
// Handle data URL
|
|
@@ -4869,7 +4912,9 @@ export class GoogleVertexProvider extends BaseProvider {
|
|
|
4869
4912
|
try {
|
|
4870
4913
|
const response = await fetch(image);
|
|
4871
4914
|
if (!response.ok) {
|
|
4872
|
-
|
|
4915
|
+
// The URL may be presigned or carry credentials in its query
|
|
4916
|
+
// string, and wrapper URLs now reach this branch too.
|
|
4917
|
+
logger.warn(`[GoogleVertex] Image fetch failed: ${response.status} ${response.statusText}, skipping`, { url: redactUrlForError(image) });
|
|
4873
4918
|
continue;
|
|
4874
4919
|
}
|
|
4875
4920
|
const arrayBuffer = await response.arrayBuffer();
|
|
@@ -4880,7 +4925,7 @@ export class GoogleVertexProvider extends BaseProvider {
|
|
|
4880
4925
|
}
|
|
4881
4926
|
}
|
|
4882
4927
|
catch (fetchError) {
|
|
4883
|
-
logger.warn(`[GoogleVertex] Image URL fetch threw, skipping: ${fetchError instanceof Error ? fetchError.message : String(fetchError)}`, { url: image });
|
|
4928
|
+
logger.warn(`[GoogleVertex] Image URL fetch threw, skipping: ${fetchError instanceof Error ? fetchError.message : String(fetchError)}`, { url: redactUrlForError(image) });
|
|
4884
4929
|
continue;
|
|
4885
4930
|
}
|
|
4886
4931
|
}
|
|
@@ -7043,6 +7088,14 @@ export class GoogleVertexProvider extends BaseProvider {
|
|
|
7043
7088
|
* @returns A promise that resolves to the generation result, including the image data.
|
|
7044
7089
|
*/
|
|
7045
7090
|
async executeImageGeneration(options) {
|
|
7091
|
+
// Image-to-image generation takes reference images through the same
|
|
7092
|
+
// `input.images` array, and both generate() and stream() route here BEFORE
|
|
7093
|
+
// reaching preprocessNativeFileInput's normalization — so a reference photo
|
|
7094
|
+
// in HEIC/BMP/AVIF would arrive at the API untranscoded. Normalizing at the
|
|
7095
|
+
// top of this method covers every route in, rather than relying on each of
|
|
7096
|
+
// the several call sites to remember. Idempotent, so an already-normalized
|
|
7097
|
+
// request pays nothing.
|
|
7098
|
+
await normalizeVisionImageFormats(options.input);
|
|
7046
7099
|
const prompt = options.prompt || options.input?.text || "";
|
|
7047
7100
|
const pdfFiles = options.input?.pdfFiles || [];
|
|
7048
7101
|
const inputImages = options.input?.images || [];
|
|
@@ -7159,7 +7212,11 @@ export class GoogleVertexProvider extends BaseProvider {
|
|
|
7159
7212
|
// This handles the case where PDFs are converted to images for models that don't support native PDF
|
|
7160
7213
|
if (hasImageInput) {
|
|
7161
7214
|
for (let i = 0; i < inputImages.length; i++) {
|
|
7162
|
-
|
|
7215
|
+
// A fifth image loop that predates the four above and has the same
|
|
7216
|
+
// blind spot: an ImageWithAltText wrapper matches neither the Buffer
|
|
7217
|
+
// nor the string branch, so a wrapped reference image was silently
|
|
7218
|
+
// skipped — including one this method had just transcoded.
|
|
7219
|
+
const image = unwrapImagePayload(inputImages[i]);
|
|
7163
7220
|
let imageBase64;
|
|
7164
7221
|
let mimeType;
|
|
7165
7222
|
if (Buffer.isBuffer(image)) {
|
|
@@ -7208,7 +7265,7 @@ export class GoogleVertexProvider extends BaseProvider {
|
|
|
7208
7265
|
try {
|
|
7209
7266
|
const response = await fetch(image);
|
|
7210
7267
|
if (!response.ok) {
|
|
7211
|
-
logger.warn(`Image fetch failed: ${response.status} ${response.statusText}, skipping`, { url: image, index: i });
|
|
7268
|
+
logger.warn(`Image fetch failed: ${response.status} ${response.statusText}, skipping`, { url: redactUrlForError(image), index: i });
|
|
7212
7269
|
continue;
|
|
7213
7270
|
}
|
|
7214
7271
|
const arrayBuffer = await response.arrayBuffer();
|
|
@@ -7221,7 +7278,7 @@ export class GoogleVertexProvider extends BaseProvider {
|
|
|
7221
7278
|
: this.detectImageType(fetchedBuffer);
|
|
7222
7279
|
}
|
|
7223
7280
|
catch (fetchError) {
|
|
7224
|
-
logger.warn(`Image URL fetch threw, skipping: ${fetchError instanceof Error ? fetchError.message : String(fetchError)}`, { url: image, index: i });
|
|
7281
|
+
logger.warn(`Image URL fetch threw, skipping: ${fetchError instanceof Error ? fetchError.message : String(fetchError)}`, { url: redactUrlForError(image), index: i });
|
|
7225
7282
|
continue;
|
|
7226
7283
|
}
|
|
7227
7284
|
}
|
package/dist/lib/types/file.d.ts
CHANGED
|
@@ -9,6 +9,47 @@ export type FileType = "csv" | "image" | "pdf" | "audio" | "video" | "archive" |
|
|
|
9
9
|
* Office document types
|
|
10
10
|
*/
|
|
11
11
|
export type OfficeDocumentType = "docx" | "pptx" | "xlsx";
|
|
12
|
+
/**
|
|
13
|
+
* Outcome of a vision-compatibility pass over one image.
|
|
14
|
+
*
|
|
15
|
+
* See `adapters/imageFormatSupport.ts` — `converted` is false both when the
|
|
16
|
+
* source format was already universally accepted and when no decoder could
|
|
17
|
+
* read it, so callers must not treat it as a success flag.
|
|
18
|
+
*/
|
|
19
|
+
export type VisionImageConversion = {
|
|
20
|
+
readonly buffer: Buffer;
|
|
21
|
+
readonly mimeType: string;
|
|
22
|
+
/** True when the bytes were re-encoded; false when they were left alone. */
|
|
23
|
+
readonly converted: boolean;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Broad category a file format belongs to, as a human would name it.
|
|
27
|
+
*
|
|
28
|
+
* Distinct from {@link FileType}, which is the *routing* type the detector
|
|
29
|
+
* emits. The two deliberately differ where one processor handles several
|
|
30
|
+
* formats: an .odt has `modality: "document"` but `fileType: "docx"`, and a
|
|
31
|
+
* .svg has `modality: "image"` but `fileType: "svg"` because it is sanitised as
|
|
32
|
+
* markup rather than sent to a vision API.
|
|
33
|
+
*/
|
|
34
|
+
export type FileModality = "image" | "audio" | "video" | "document" | "data" | "archive";
|
|
35
|
+
/**
|
|
36
|
+
* One format in the canonical file-type registry.
|
|
37
|
+
*
|
|
38
|
+
* `extensions[0]` and `mimeTypes[0]` are canonical; the remaining entries are
|
|
39
|
+
* aliases accepted on input. See `processors/config/fileTypeRegistry.ts`.
|
|
40
|
+
*/
|
|
41
|
+
export type FileFormatEntry = {
|
|
42
|
+
/** Human-readable format name, used in registry-conflict errors. */
|
|
43
|
+
readonly label: string;
|
|
44
|
+
/** Extensions with leading dots, lowercase; first is canonical. */
|
|
45
|
+
readonly extensions: readonly string[];
|
|
46
|
+
/** MIME types, lowercase; first is canonical. */
|
|
47
|
+
readonly mimeTypes: readonly string[];
|
|
48
|
+
/** Routing type the detector emits for this format. */
|
|
49
|
+
readonly fileType: FileType;
|
|
50
|
+
/** Category a human would put this format in. */
|
|
51
|
+
readonly modality: FileModality;
|
|
52
|
+
};
|
|
12
53
|
/**
|
|
13
54
|
* File with metadata — allows callers to pass filename alongside a Buffer.
|
|
14
55
|
*
|