@juspay/neurolink 9.10.0 → 9.10.1
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/video/videoAnalyzer.d.ts +3 -3
- package/dist/adapters/video/videoAnalyzer.js +39 -25
- package/dist/core/baseProvider.js +14 -0
- package/dist/lib/adapters/video/videoAnalyzer.d.ts +3 -3
- package/dist/lib/adapters/video/videoAnalyzer.js +39 -25
- package/dist/lib/core/baseProvider.js +14 -0
- package/dist/lib/utils/videoAnalysisProcessor.d.ts +2 -1
- package/dist/lib/utils/videoAnalysisProcessor.js +7 -2
- package/dist/utils/videoAnalysisProcessor.d.ts +2 -1
- package/dist/utils/videoAnalysisProcessor.js +7 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
## [9.10.1](https://github.com/juspay/neurolink/compare/v9.10.0...v9.10.1) (2026-02-21)
|
|
2
|
+
|
|
3
|
+
### Bug Fixes
|
|
4
|
+
|
|
5
|
+
- **(video-analysis):** add stream support for video analysis ([938aeef](https://github.com/juspay/neurolink/commit/938aeef876277360700d2a7192155af1f1316f28))
|
|
6
|
+
|
|
1
7
|
## [9.10.0](https://github.com/juspay/neurolink/compare/v9.9.0...v9.10.0) (2026-02-20)
|
|
2
8
|
|
|
3
9
|
### Features
|
|
@@ -8,16 +8,16 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { AIProviderName } from "../../constants/enums.js";
|
|
10
10
|
import type { CoreMessage } from "ai";
|
|
11
|
-
export declare function analyzeVideoWithVertexAI(
|
|
11
|
+
export declare function analyzeVideoWithVertexAI(messages: CoreMessage[], options?: {
|
|
12
12
|
project?: string;
|
|
13
13
|
location?: string;
|
|
14
14
|
model?: string;
|
|
15
15
|
}): Promise<string>;
|
|
16
|
-
export declare function analyzeVideoWithGeminiAPI(
|
|
16
|
+
export declare function analyzeVideoWithGeminiAPI(messages: CoreMessage[], options?: {
|
|
17
17
|
apiKey?: string;
|
|
18
18
|
model?: string;
|
|
19
19
|
}): Promise<string>;
|
|
20
|
-
export declare function analyzeVideo(
|
|
20
|
+
export declare function analyzeVideo(messages: CoreMessage[], options?: {
|
|
21
21
|
provider?: AIProviderName;
|
|
22
22
|
project?: string;
|
|
23
23
|
location?: string;
|
|
@@ -9,23 +9,35 @@
|
|
|
9
9
|
import { AIProviderName, ErrorSeverity, ErrorCategory, } from "../../constants/enums.js";
|
|
10
10
|
import { logger } from "../../utils/logger.js";
|
|
11
11
|
import { readFile } from "node:fs/promises";
|
|
12
|
-
import { NeuroLinkError } from "../../utils/errorHandling.js";
|
|
12
|
+
import { NeuroLinkError, ErrorFactory } from "../../utils/errorHandling.js";
|
|
13
13
|
// ---------------------------------------------------------------------------
|
|
14
14
|
// Shared config
|
|
15
15
|
// ---------------------------------------------------------------------------
|
|
16
16
|
const DEFAULT_MODEL = "gemini-2.0-flash";
|
|
17
17
|
const DEFAULT_LOCATION = "us-central1";
|
|
18
|
+
/**
|
|
19
|
+
* Extract content items from user messages
|
|
20
|
+
*
|
|
21
|
+
* @param messages - Array of CoreMessage objects
|
|
22
|
+
* @returns Flattened array of content items from user messages
|
|
23
|
+
*/
|
|
24
|
+
function extractUserContent(messages) {
|
|
25
|
+
const userMessages = messages.filter((msg) => msg.role === "user");
|
|
26
|
+
return userMessages.flatMap((msg) => Array.isArray(msg.content) ? msg.content : []);
|
|
27
|
+
}
|
|
18
28
|
/**
|
|
19
29
|
* Convert CoreMessage content array to Gemini parts format
|
|
20
30
|
*
|
|
21
|
-
* @param
|
|
31
|
+
* @param messages - Array of CoreMessage objects
|
|
22
32
|
* @returns Array of parts in Gemini API format
|
|
23
33
|
*/
|
|
24
|
-
function buildContentParts(
|
|
25
|
-
const
|
|
26
|
-
return
|
|
27
|
-
|
|
28
|
-
|
|
34
|
+
function buildContentParts(messages) {
|
|
35
|
+
const allContent = extractUserContent(messages);
|
|
36
|
+
return allContent
|
|
37
|
+
.map((item) => {
|
|
38
|
+
if (item.type === "text") {
|
|
39
|
+
// Accept text parts regardless of whether text is empty
|
|
40
|
+
return { text: item.text || "" };
|
|
29
41
|
}
|
|
30
42
|
else if (item.type === "image" && item.image) {
|
|
31
43
|
let base64Data;
|
|
@@ -38,7 +50,7 @@ function buildContentParts(frames) {
|
|
|
38
50
|
base64Data = item.image.replace(/^data:image\/[a-z]+;base64,/, "");
|
|
39
51
|
}
|
|
40
52
|
else {
|
|
41
|
-
throw
|
|
53
|
+
throw ErrorFactory.invalidConfiguration("image data type", `expected string, Buffer, or Uint8Array, got ${typeof item.image}`, { itemType: item.type, dataType: typeof item.image });
|
|
42
54
|
}
|
|
43
55
|
return {
|
|
44
56
|
inlineData: {
|
|
@@ -47,8 +59,14 @@ function buildContentParts(frames) {
|
|
|
47
59
|
},
|
|
48
60
|
};
|
|
49
61
|
}
|
|
50
|
-
|
|
51
|
-
|
|
62
|
+
else if (item.type === "file") {
|
|
63
|
+
// Skip file parts - not supported in Gemini parts format
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
// Return null for unsupported types
|
|
67
|
+
return null;
|
|
68
|
+
})
|
|
69
|
+
.filter((part) => part !== null);
|
|
52
70
|
}
|
|
53
71
|
/**
|
|
54
72
|
* Configuration for video frame analysis.
|
|
@@ -88,7 +106,7 @@ Ensure the final response is fully self-sufficient and does not reference extern
|
|
|
88
106
|
// ---------------------------------------------------------------------------
|
|
89
107
|
// Vertex AI
|
|
90
108
|
// ---------------------------------------------------------------------------
|
|
91
|
-
export async function analyzeVideoWithVertexAI(
|
|
109
|
+
export async function analyzeVideoWithVertexAI(messages, options = {}) {
|
|
92
110
|
const startTime = Date.now();
|
|
93
111
|
const { GoogleGenAI } = await import("@google/genai");
|
|
94
112
|
// Get default config and merge with provided options
|
|
@@ -96,9 +114,9 @@ export async function analyzeVideoWithVertexAI(frames, options = {}) {
|
|
|
96
114
|
const project = options.project ?? config.project;
|
|
97
115
|
const location = options.location ?? config.location;
|
|
98
116
|
const model = options.model || DEFAULT_MODEL;
|
|
99
|
-
//
|
|
100
|
-
const
|
|
101
|
-
const frameCount =
|
|
117
|
+
// Convert frames content to parts array for Gemini
|
|
118
|
+
const parts = buildContentParts(messages);
|
|
119
|
+
const frameCount = parts.filter((part) => "inlineData" in part && part.inlineData).length;
|
|
102
120
|
logger.debug("[GeminiVideoAnalyzer] Analyzing video with Vertex AI", {
|
|
103
121
|
project,
|
|
104
122
|
location,
|
|
@@ -106,8 +124,6 @@ export async function analyzeVideoWithVertexAI(frames, options = {}) {
|
|
|
106
124
|
frameCount,
|
|
107
125
|
});
|
|
108
126
|
const ai = new GoogleGenAI({ vertexai: true, project, location });
|
|
109
|
-
// Convert frames content to parts array for Gemini
|
|
110
|
-
const parts = buildContentParts(frames);
|
|
111
127
|
const response = await ai.models.generateContent({
|
|
112
128
|
model,
|
|
113
129
|
config: buildConfig(),
|
|
@@ -129,7 +145,7 @@ export async function analyzeVideoWithVertexAI(frames, options = {}) {
|
|
|
129
145
|
// ---------------------------------------------------------------------------
|
|
130
146
|
// Gemini API (Google AI)
|
|
131
147
|
// ---------------------------------------------------------------------------
|
|
132
|
-
export async function analyzeVideoWithGeminiAPI(
|
|
148
|
+
export async function analyzeVideoWithGeminiAPI(messages, options = {}) {
|
|
133
149
|
const startTime = Date.now();
|
|
134
150
|
const { GoogleGenAI } = await import("@google/genai");
|
|
135
151
|
const apiKey = options.apiKey || process.env.GOOGLE_AI_API_KEY;
|
|
@@ -137,16 +153,14 @@ export async function analyzeVideoWithGeminiAPI(frames, options = {}) {
|
|
|
137
153
|
if (!apiKey) {
|
|
138
154
|
throw new Error("GOOGLE_AI_API_KEY environment variable is required for Gemini API video analysis");
|
|
139
155
|
}
|
|
140
|
-
//
|
|
141
|
-
const
|
|
142
|
-
const frameCount =
|
|
156
|
+
// Convert frames content to parts array for Gemini
|
|
157
|
+
const parts = buildContentParts(messages);
|
|
158
|
+
const frameCount = parts.filter((part) => "inlineData" in part && part.inlineData).length;
|
|
143
159
|
logger.debug("[GeminiVideoAnalyzer] Analyzing video with Gemini API", {
|
|
144
160
|
model,
|
|
145
161
|
frameCount,
|
|
146
162
|
});
|
|
147
163
|
const ai = new GoogleGenAI({ apiKey });
|
|
148
|
-
// Convert frames content to parts array for Gemini
|
|
149
|
-
const parts = buildContentParts(frames);
|
|
150
164
|
logger.debug("[GeminiVideoAnalyzer] Generating analysis with frames");
|
|
151
165
|
const response = await ai.models.generateContent({
|
|
152
166
|
model,
|
|
@@ -207,15 +221,15 @@ async function getVertexConfig() {
|
|
|
207
221
|
}
|
|
208
222
|
return { project, location };
|
|
209
223
|
}
|
|
210
|
-
export async function analyzeVideo(
|
|
224
|
+
export async function analyzeVideo(messages, options = {}) {
|
|
211
225
|
const provider = options.provider || AIProviderName.AUTO;
|
|
212
226
|
// Vertex — only when GOOGLE_VERTEX_PROJECT is explicitly set
|
|
213
227
|
if (provider === AIProviderName.VERTEX || provider === AIProviderName.AUTO) {
|
|
214
|
-
return analyzeVideoWithVertexAI(
|
|
228
|
+
return analyzeVideoWithVertexAI(messages, options);
|
|
215
229
|
}
|
|
216
230
|
// Gemini API — when GOOGLE_AI_API_KEY is set
|
|
217
231
|
if (provider === AIProviderName.GOOGLE_AI && process.env.GOOGLE_AI_API_KEY) {
|
|
218
|
-
return analyzeVideoWithGeminiAPI(
|
|
232
|
+
return analyzeVideoWithGeminiAPI(messages, options);
|
|
219
233
|
}
|
|
220
234
|
throw new Error("No valid provider configuration found. " +
|
|
221
235
|
"Set GOOGLE_VERTEX_PROJECT for Vertex AI or GOOGLE_AI_API_KEY for Gemini API.");
|
|
@@ -86,6 +86,20 @@ export class BaseProvider {
|
|
|
86
86
|
temperature: options.temperature,
|
|
87
87
|
timestamp: Date.now(),
|
|
88
88
|
});
|
|
89
|
+
// ===== EARLY MULTIMODAL DETECTION =====
|
|
90
|
+
const hasFileInput = !!options.input?.files?.length || !!options.input?.videoFiles?.length;
|
|
91
|
+
if (hasFileInput) {
|
|
92
|
+
// ===== VIDEO ANALYSIS DETECTION =====
|
|
93
|
+
// Check if video frames are present and handle with fake streaming
|
|
94
|
+
const messages = await this.buildMessagesForStream(options);
|
|
95
|
+
if (hasVideoFrames(messages)) {
|
|
96
|
+
logger.info(`Video frames detected in stream, using fake streaming for video analysis`, {
|
|
97
|
+
provider: this.providerName,
|
|
98
|
+
model: this.modelName,
|
|
99
|
+
});
|
|
100
|
+
return await this.executeFakeStreaming(options, analysisSchema);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
89
103
|
// 🔧 CRITICAL: Image generation models don't support real streaming
|
|
90
104
|
// Force fake streaming for image models to ensure image output is yielded
|
|
91
105
|
const isImageModel = IMAGE_GENERATION_MODELS.some((m) => this.modelName.includes(m));
|
|
@@ -8,16 +8,16 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { AIProviderName } from "../../constants/enums.js";
|
|
10
10
|
import type { CoreMessage } from "ai";
|
|
11
|
-
export declare function analyzeVideoWithVertexAI(
|
|
11
|
+
export declare function analyzeVideoWithVertexAI(messages: CoreMessage[], options?: {
|
|
12
12
|
project?: string;
|
|
13
13
|
location?: string;
|
|
14
14
|
model?: string;
|
|
15
15
|
}): Promise<string>;
|
|
16
|
-
export declare function analyzeVideoWithGeminiAPI(
|
|
16
|
+
export declare function analyzeVideoWithGeminiAPI(messages: CoreMessage[], options?: {
|
|
17
17
|
apiKey?: string;
|
|
18
18
|
model?: string;
|
|
19
19
|
}): Promise<string>;
|
|
20
|
-
export declare function analyzeVideo(
|
|
20
|
+
export declare function analyzeVideo(messages: CoreMessage[], options?: {
|
|
21
21
|
provider?: AIProviderName;
|
|
22
22
|
project?: string;
|
|
23
23
|
location?: string;
|
|
@@ -9,23 +9,35 @@
|
|
|
9
9
|
import { AIProviderName, ErrorSeverity, ErrorCategory, } from "../../constants/enums.js";
|
|
10
10
|
import { logger } from "../../utils/logger.js";
|
|
11
11
|
import { readFile } from "node:fs/promises";
|
|
12
|
-
import { NeuroLinkError } from "../../utils/errorHandling.js";
|
|
12
|
+
import { NeuroLinkError, ErrorFactory } from "../../utils/errorHandling.js";
|
|
13
13
|
// ---------------------------------------------------------------------------
|
|
14
14
|
// Shared config
|
|
15
15
|
// ---------------------------------------------------------------------------
|
|
16
16
|
const DEFAULT_MODEL = "gemini-2.0-flash";
|
|
17
17
|
const DEFAULT_LOCATION = "us-central1";
|
|
18
|
+
/**
|
|
19
|
+
* Extract content items from user messages
|
|
20
|
+
*
|
|
21
|
+
* @param messages - Array of CoreMessage objects
|
|
22
|
+
* @returns Flattened array of content items from user messages
|
|
23
|
+
*/
|
|
24
|
+
function extractUserContent(messages) {
|
|
25
|
+
const userMessages = messages.filter((msg) => msg.role === "user");
|
|
26
|
+
return userMessages.flatMap((msg) => Array.isArray(msg.content) ? msg.content : []);
|
|
27
|
+
}
|
|
18
28
|
/**
|
|
19
29
|
* Convert CoreMessage content array to Gemini parts format
|
|
20
30
|
*
|
|
21
|
-
* @param
|
|
31
|
+
* @param messages - Array of CoreMessage objects
|
|
22
32
|
* @returns Array of parts in Gemini API format
|
|
23
33
|
*/
|
|
24
|
-
function buildContentParts(
|
|
25
|
-
const
|
|
26
|
-
return
|
|
27
|
-
|
|
28
|
-
|
|
34
|
+
function buildContentParts(messages) {
|
|
35
|
+
const allContent = extractUserContent(messages);
|
|
36
|
+
return allContent
|
|
37
|
+
.map((item) => {
|
|
38
|
+
if (item.type === "text") {
|
|
39
|
+
// Accept text parts regardless of whether text is empty
|
|
40
|
+
return { text: item.text || "" };
|
|
29
41
|
}
|
|
30
42
|
else if (item.type === "image" && item.image) {
|
|
31
43
|
let base64Data;
|
|
@@ -38,7 +50,7 @@ function buildContentParts(frames) {
|
|
|
38
50
|
base64Data = item.image.replace(/^data:image\/[a-z]+;base64,/, "");
|
|
39
51
|
}
|
|
40
52
|
else {
|
|
41
|
-
throw
|
|
53
|
+
throw ErrorFactory.invalidConfiguration("image data type", `expected string, Buffer, or Uint8Array, got ${typeof item.image}`, { itemType: item.type, dataType: typeof item.image });
|
|
42
54
|
}
|
|
43
55
|
return {
|
|
44
56
|
inlineData: {
|
|
@@ -47,8 +59,14 @@ function buildContentParts(frames) {
|
|
|
47
59
|
},
|
|
48
60
|
};
|
|
49
61
|
}
|
|
50
|
-
|
|
51
|
-
|
|
62
|
+
else if (item.type === "file") {
|
|
63
|
+
// Skip file parts - not supported in Gemini parts format
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
// Return null for unsupported types
|
|
67
|
+
return null;
|
|
68
|
+
})
|
|
69
|
+
.filter((part) => part !== null);
|
|
52
70
|
}
|
|
53
71
|
/**
|
|
54
72
|
* Configuration for video frame analysis.
|
|
@@ -88,7 +106,7 @@ Ensure the final response is fully self-sufficient and does not reference extern
|
|
|
88
106
|
// ---------------------------------------------------------------------------
|
|
89
107
|
// Vertex AI
|
|
90
108
|
// ---------------------------------------------------------------------------
|
|
91
|
-
export async function analyzeVideoWithVertexAI(
|
|
109
|
+
export async function analyzeVideoWithVertexAI(messages, options = {}) {
|
|
92
110
|
const startTime = Date.now();
|
|
93
111
|
const { GoogleGenAI } = await import("@google/genai");
|
|
94
112
|
// Get default config and merge with provided options
|
|
@@ -96,9 +114,9 @@ export async function analyzeVideoWithVertexAI(frames, options = {}) {
|
|
|
96
114
|
const project = options.project ?? config.project;
|
|
97
115
|
const location = options.location ?? config.location;
|
|
98
116
|
const model = options.model || DEFAULT_MODEL;
|
|
99
|
-
//
|
|
100
|
-
const
|
|
101
|
-
const frameCount =
|
|
117
|
+
// Convert frames content to parts array for Gemini
|
|
118
|
+
const parts = buildContentParts(messages);
|
|
119
|
+
const frameCount = parts.filter((part) => "inlineData" in part && part.inlineData).length;
|
|
102
120
|
logger.debug("[GeminiVideoAnalyzer] Analyzing video with Vertex AI", {
|
|
103
121
|
project,
|
|
104
122
|
location,
|
|
@@ -106,8 +124,6 @@ export async function analyzeVideoWithVertexAI(frames, options = {}) {
|
|
|
106
124
|
frameCount,
|
|
107
125
|
});
|
|
108
126
|
const ai = new GoogleGenAI({ vertexai: true, project, location });
|
|
109
|
-
// Convert frames content to parts array for Gemini
|
|
110
|
-
const parts = buildContentParts(frames);
|
|
111
127
|
const response = await ai.models.generateContent({
|
|
112
128
|
model,
|
|
113
129
|
config: buildConfig(),
|
|
@@ -129,7 +145,7 @@ export async function analyzeVideoWithVertexAI(frames, options = {}) {
|
|
|
129
145
|
// ---------------------------------------------------------------------------
|
|
130
146
|
// Gemini API (Google AI)
|
|
131
147
|
// ---------------------------------------------------------------------------
|
|
132
|
-
export async function analyzeVideoWithGeminiAPI(
|
|
148
|
+
export async function analyzeVideoWithGeminiAPI(messages, options = {}) {
|
|
133
149
|
const startTime = Date.now();
|
|
134
150
|
const { GoogleGenAI } = await import("@google/genai");
|
|
135
151
|
const apiKey = options.apiKey || process.env.GOOGLE_AI_API_KEY;
|
|
@@ -137,16 +153,14 @@ export async function analyzeVideoWithGeminiAPI(frames, options = {}) {
|
|
|
137
153
|
if (!apiKey) {
|
|
138
154
|
throw new Error("GOOGLE_AI_API_KEY environment variable is required for Gemini API video analysis");
|
|
139
155
|
}
|
|
140
|
-
//
|
|
141
|
-
const
|
|
142
|
-
const frameCount =
|
|
156
|
+
// Convert frames content to parts array for Gemini
|
|
157
|
+
const parts = buildContentParts(messages);
|
|
158
|
+
const frameCount = parts.filter((part) => "inlineData" in part && part.inlineData).length;
|
|
143
159
|
logger.debug("[GeminiVideoAnalyzer] Analyzing video with Gemini API", {
|
|
144
160
|
model,
|
|
145
161
|
frameCount,
|
|
146
162
|
});
|
|
147
163
|
const ai = new GoogleGenAI({ apiKey });
|
|
148
|
-
// Convert frames content to parts array for Gemini
|
|
149
|
-
const parts = buildContentParts(frames);
|
|
150
164
|
logger.debug("[GeminiVideoAnalyzer] Generating analysis with frames");
|
|
151
165
|
const response = await ai.models.generateContent({
|
|
152
166
|
model,
|
|
@@ -207,15 +221,15 @@ async function getVertexConfig() {
|
|
|
207
221
|
}
|
|
208
222
|
return { project, location };
|
|
209
223
|
}
|
|
210
|
-
export async function analyzeVideo(
|
|
224
|
+
export async function analyzeVideo(messages, options = {}) {
|
|
211
225
|
const provider = options.provider || AIProviderName.AUTO;
|
|
212
226
|
// Vertex — only when GOOGLE_VERTEX_PROJECT is explicitly set
|
|
213
227
|
if (provider === AIProviderName.VERTEX || provider === AIProviderName.AUTO) {
|
|
214
|
-
return analyzeVideoWithVertexAI(
|
|
228
|
+
return analyzeVideoWithVertexAI(messages, options);
|
|
215
229
|
}
|
|
216
230
|
// Gemini API — when GOOGLE_AI_API_KEY is set
|
|
217
231
|
if (provider === AIProviderName.GOOGLE_AI && process.env.GOOGLE_AI_API_KEY) {
|
|
218
|
-
return analyzeVideoWithGeminiAPI(
|
|
232
|
+
return analyzeVideoWithGeminiAPI(messages, options);
|
|
219
233
|
}
|
|
220
234
|
throw new Error("No valid provider configuration found. " +
|
|
221
235
|
"Set GOOGLE_VERTEX_PROJECT for Vertex AI or GOOGLE_AI_API_KEY for Gemini API.");
|
|
@@ -86,6 +86,20 @@ export class BaseProvider {
|
|
|
86
86
|
temperature: options.temperature,
|
|
87
87
|
timestamp: Date.now(),
|
|
88
88
|
});
|
|
89
|
+
// ===== EARLY MULTIMODAL DETECTION =====
|
|
90
|
+
const hasFileInput = !!options.input?.files?.length || !!options.input?.videoFiles?.length;
|
|
91
|
+
if (hasFileInput) {
|
|
92
|
+
// ===== VIDEO ANALYSIS DETECTION =====
|
|
93
|
+
// Check if video frames are present and handle with fake streaming
|
|
94
|
+
const messages = await this.buildMessagesForStream(options);
|
|
95
|
+
if (hasVideoFrames(messages)) {
|
|
96
|
+
logger.info(`Video frames detected in stream, using fake streaming for video analysis`, {
|
|
97
|
+
provider: this.providerName,
|
|
98
|
+
model: this.modelName,
|
|
99
|
+
});
|
|
100
|
+
return await this.executeFakeStreaming(options, analysisSchema);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
89
103
|
// 🔧 CRITICAL: Image generation models don't support real streaming
|
|
90
104
|
// Force fake streaming for image models to ensure image output is yielded
|
|
91
105
|
const isImageModel = IMAGE_GENERATION_MODELS.some((m) => this.modelName.includes(m));
|
|
@@ -9,9 +9,10 @@ import type { CoreMessage } from "ai";
|
|
|
9
9
|
import { AIProviderName } from "../constants/enums.js";
|
|
10
10
|
/**
|
|
11
11
|
* Check if messages contain video frames (images)
|
|
12
|
+
* Only checks user messages to match buildContentParts behavior
|
|
12
13
|
*
|
|
13
14
|
* @param messages - Array of CoreMessage objects
|
|
14
|
-
* @returns true if video frames are present
|
|
15
|
+
* @returns true if video frames are present in user messages
|
|
15
16
|
*/
|
|
16
17
|
export declare function hasVideoFrames(messages: CoreMessage[]): boolean;
|
|
17
18
|
/**
|
|
@@ -9,12 +9,17 @@ import { AIProviderName } from "../constants/enums.js";
|
|
|
9
9
|
import { logger } from "./logger.js";
|
|
10
10
|
/**
|
|
11
11
|
* Check if messages contain video frames (images)
|
|
12
|
+
* Only checks user messages to match buildContentParts behavior
|
|
12
13
|
*
|
|
13
14
|
* @param messages - Array of CoreMessage objects
|
|
14
|
-
* @returns true if video frames are present
|
|
15
|
+
* @returns true if video frames are present in user messages
|
|
15
16
|
*/
|
|
16
17
|
export function hasVideoFrames(messages) {
|
|
17
18
|
return messages.some((msg) => {
|
|
19
|
+
// Only check user messages to match buildContentParts behavior
|
|
20
|
+
if (msg.role !== "user") {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
18
23
|
if (Array.isArray(msg.content)) {
|
|
19
24
|
return msg.content.some((part) => typeof part === "object" &&
|
|
20
25
|
part !== null &&
|
|
@@ -42,7 +47,7 @@ export async function executeVideoAnalysis(messages, options) {
|
|
|
42
47
|
options.providerName === AIProviderName.VERTEX
|
|
43
48
|
? AIProviderName.VERTEX
|
|
44
49
|
: AIProviderName.AUTO;
|
|
45
|
-
const videoAnalysisText = await analyzeVideo(messages
|
|
50
|
+
const videoAnalysisText = await analyzeVideo(messages, {
|
|
46
51
|
provider: provider,
|
|
47
52
|
project: options.region
|
|
48
53
|
? undefined
|
|
@@ -9,9 +9,10 @@ import type { CoreMessage } from "ai";
|
|
|
9
9
|
import { AIProviderName } from "../constants/enums.js";
|
|
10
10
|
/**
|
|
11
11
|
* Check if messages contain video frames (images)
|
|
12
|
+
* Only checks user messages to match buildContentParts behavior
|
|
12
13
|
*
|
|
13
14
|
* @param messages - Array of CoreMessage objects
|
|
14
|
-
* @returns true if video frames are present
|
|
15
|
+
* @returns true if video frames are present in user messages
|
|
15
16
|
*/
|
|
16
17
|
export declare function hasVideoFrames(messages: CoreMessage[]): boolean;
|
|
17
18
|
/**
|
|
@@ -9,12 +9,17 @@ import { AIProviderName } from "../constants/enums.js";
|
|
|
9
9
|
import { logger } from "./logger.js";
|
|
10
10
|
/**
|
|
11
11
|
* Check if messages contain video frames (images)
|
|
12
|
+
* Only checks user messages to match buildContentParts behavior
|
|
12
13
|
*
|
|
13
14
|
* @param messages - Array of CoreMessage objects
|
|
14
|
-
* @returns true if video frames are present
|
|
15
|
+
* @returns true if video frames are present in user messages
|
|
15
16
|
*/
|
|
16
17
|
export function hasVideoFrames(messages) {
|
|
17
18
|
return messages.some((msg) => {
|
|
19
|
+
// Only check user messages to match buildContentParts behavior
|
|
20
|
+
if (msg.role !== "user") {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
18
23
|
if (Array.isArray(msg.content)) {
|
|
19
24
|
return msg.content.some((part) => typeof part === "object" &&
|
|
20
25
|
part !== null &&
|
|
@@ -42,7 +47,7 @@ export async function executeVideoAnalysis(messages, options) {
|
|
|
42
47
|
options.providerName === AIProviderName.VERTEX
|
|
43
48
|
? AIProviderName.VERTEX
|
|
44
49
|
: AIProviderName.AUTO;
|
|
45
|
-
const videoAnalysisText = await analyzeVideo(messages
|
|
50
|
+
const videoAnalysisText = await analyzeVideo(messages, {
|
|
46
51
|
provider: provider,
|
|
47
52
|
project: options.region
|
|
48
53
|
? undefined
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juspay/neurolink",
|
|
3
|
-
"version": "9.10.
|
|
3
|
+
"version": "9.10.1",
|
|
4
4
|
"description": "Universal AI Development Platform with working MCP integration, multi-provider support, and professional CLI. Built-in tools operational, 58+ external MCP servers discoverable. Connect to filesystem, GitHub, database operations, and more. Build, test, and deploy AI applications with 13 providers: OpenAI, Anthropic, Google AI, AWS Bedrock, Azure, Hugging Face, Ollama, and Mistral AI.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Juspay Technologies",
|