@juspay/neurolink 11.27.0 → 11.29.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 +2 -2
- package/dist/adapters/video/index.d.ts +30 -0
- package/dist/adapters/video/index.js +74 -0
- package/dist/avatar/index.d.ts +6 -3
- package/dist/avatar/index.js +21 -16
- package/dist/browser/neurolink.min.js +392 -392
- package/dist/cli/factories/commandFactory.d.ts +6 -0
- package/dist/cli/factories/commandFactory.js +6 -2
- package/dist/core/baseProvider.js +24 -20
- package/dist/core/resolveRequestKind.d.ts +27 -0
- package/dist/core/resolveRequestKind.js +50 -0
- package/dist/factories/mediaHandlerCatalog.d.ts +18 -0
- package/dist/factories/mediaHandlerCatalog.js +65 -0
- package/dist/factories/providerRegistry.js +50 -207
- package/dist/index.d.ts +1 -4
- package/dist/index.js +2 -5
- package/dist/music/index.d.ts +6 -3
- package/dist/music/index.js +22 -21
- package/dist/neurolink.js +19 -3
- package/dist/types/dispatch.d.ts +22 -0
- package/dist/types/dispatch.js +6 -0
- package/dist/types/generate.d.ts +29 -37
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.js +3 -0
- package/dist/types/mediaCatalog.d.ts +12 -0
- package/dist/types/mediaCatalog.js +7 -0
- package/dist/types/video.d.ts +13 -0
- package/dist/utils/videoProcessor.d.ts +11 -5
- package/dist/utils/videoProcessor.js +23 -16
- package/dist/voice/index.d.ts +7 -3
- package/dist/voice/index.js +50 -40
- package/package.json +3 -1
|
@@ -300,6 +300,7 @@ export declare class CLICommandFactory {
|
|
|
300
300
|
};
|
|
301
301
|
videoProvider: {
|
|
302
302
|
type: "string";
|
|
303
|
+
choices: string[];
|
|
303
304
|
description: string;
|
|
304
305
|
};
|
|
305
306
|
videoOutput: {
|
|
@@ -328,6 +329,7 @@ export declare class CLICommandFactory {
|
|
|
328
329
|
};
|
|
329
330
|
avatarProvider: {
|
|
330
331
|
type: "string";
|
|
332
|
+
choices: string[];
|
|
331
333
|
description: string;
|
|
332
334
|
};
|
|
333
335
|
avatarImage: {
|
|
@@ -362,6 +364,7 @@ export declare class CLICommandFactory {
|
|
|
362
364
|
};
|
|
363
365
|
musicProvider: {
|
|
364
366
|
type: "string";
|
|
367
|
+
choices: string[];
|
|
365
368
|
description: string;
|
|
366
369
|
};
|
|
367
370
|
musicDuration: {
|
|
@@ -1190,6 +1193,7 @@ export declare const commonOptions: {
|
|
|
1190
1193
|
};
|
|
1191
1194
|
videoProvider: {
|
|
1192
1195
|
type: "string";
|
|
1196
|
+
choices: string[];
|
|
1193
1197
|
description: string;
|
|
1194
1198
|
};
|
|
1195
1199
|
videoOutput: {
|
|
@@ -1218,6 +1222,7 @@ export declare const commonOptions: {
|
|
|
1218
1222
|
};
|
|
1219
1223
|
avatarProvider: {
|
|
1220
1224
|
type: "string";
|
|
1225
|
+
choices: string[];
|
|
1221
1226
|
description: string;
|
|
1222
1227
|
};
|
|
1223
1228
|
avatarImage: {
|
|
@@ -1252,6 +1257,7 @@ export declare const commonOptions: {
|
|
|
1252
1257
|
};
|
|
1253
1258
|
musicProvider: {
|
|
1254
1259
|
type: "string";
|
|
1260
|
+
choices: string[];
|
|
1255
1261
|
description: string;
|
|
1256
1262
|
};
|
|
1257
1263
|
musicDuration: {
|
|
@@ -3,6 +3,7 @@ import path from "node:path";
|
|
|
3
3
|
import chalk from "chalk";
|
|
4
4
|
import ora from "ora";
|
|
5
5
|
import { ModelResolver } from "../../models/modelResolver.js";
|
|
6
|
+
import { providerChoicesFor } from "../../factories/mediaHandlerCatalog.js";
|
|
6
7
|
import { globalSession } from "../../session/globalSessionState.js";
|
|
7
8
|
// Use TokenUsage from standard types - no local interface needed
|
|
8
9
|
import { ContextFactory, } from "../../types/index.js";
|
|
@@ -333,7 +334,7 @@ export class CLICommandFactory {
|
|
|
333
334
|
},
|
|
334
335
|
ttsProvider: {
|
|
335
336
|
type: "string",
|
|
336
|
-
choices:
|
|
337
|
+
choices: providerChoicesFor("tts"),
|
|
337
338
|
description: "TTS provider (overrides --provider for speech synthesis)",
|
|
338
339
|
},
|
|
339
340
|
ttsFormat: {
|
|
@@ -381,7 +382,7 @@ export class CLICommandFactory {
|
|
|
381
382
|
},
|
|
382
383
|
sttProvider: {
|
|
383
384
|
type: "string",
|
|
384
|
-
choices:
|
|
385
|
+
choices: providerChoicesFor("stt"),
|
|
385
386
|
description: "STT provider to use",
|
|
386
387
|
},
|
|
387
388
|
sttLanguage: {
|
|
@@ -401,6 +402,7 @@ export class CLICommandFactory {
|
|
|
401
402
|
},
|
|
402
403
|
videoProvider: {
|
|
403
404
|
type: "string",
|
|
405
|
+
choices: providerChoicesFor("video"),
|
|
404
406
|
description: "Video provider override (e.g., 'vertex' (default), 'kling', 'runway', 'replicate')",
|
|
405
407
|
},
|
|
406
408
|
videoOutput: {
|
|
@@ -430,6 +432,7 @@ export class CLICommandFactory {
|
|
|
430
432
|
// Avatar Generation options (D-ID, HeyGen, MuseTalk via Replicate)
|
|
431
433
|
avatarProvider: {
|
|
432
434
|
type: "string",
|
|
435
|
+
choices: providerChoicesFor("avatar"),
|
|
433
436
|
description: "Avatar provider (e.g., 'd-id' (default), 'heygen', 'replicate', 'musetalk')",
|
|
434
437
|
},
|
|
435
438
|
avatarImage: {
|
|
@@ -465,6 +468,7 @@ export class CLICommandFactory {
|
|
|
465
468
|
// Music Generation options (Beatoven, ElevenLabs, Lyria, MusicGen via Replicate)
|
|
466
469
|
musicProvider: {
|
|
467
470
|
type: "string",
|
|
471
|
+
choices: providerChoicesFor("music"),
|
|
468
472
|
description: "Music provider (e.g., 'beatoven' (default), 'elevenlabs-music', 'lyria', 'replicate', 'musicgen')",
|
|
469
473
|
},
|
|
470
474
|
musicDuration: {
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { context, SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
|
|
2
2
|
import { directAgentTools } from "../agent/directTools.js";
|
|
3
|
-
import {
|
|
3
|
+
import { defaultProviderFor } from "../factories/mediaHandlerCatalog.js";
|
|
4
4
|
import { MiddlewareFactory } from "../middleware/factory.js";
|
|
5
5
|
import { modelSupports } from "../models/modelRegistry.js";
|
|
6
|
+
import { resolveRequestKind } from "./resolveRequestKind.js";
|
|
6
7
|
import { ATTR, tracers } from "../telemetry/index.js";
|
|
7
8
|
import { ERROR_CODES, isAbortError, NeuroLinkError, } from "../utils/errorHandling.js";
|
|
8
9
|
import { ProviderError } from "../types/index.js";
|
|
@@ -238,14 +239,12 @@ export class BaseProvider {
|
|
|
238
239
|
}
|
|
239
240
|
// CRITICAL: Image generation models don't support real streaming
|
|
240
241
|
// Force fake streaming for image models to ensure image output is yielded.
|
|
241
|
-
//
|
|
242
|
-
// JSON analysis) so dual-mode models like
|
|
243
|
-
// can still perform text/structured
|
|
244
|
-
|
|
245
|
-
const
|
|
246
|
-
|
|
247
|
-
options.output?.format === "text";
|
|
248
|
-
if (isImageModel && !requestsNonImageOutput) {
|
|
242
|
+
// resolveRequestKind() skips this path when the caller explicitly requests
|
|
243
|
+
// non-image output (e.g. JSON analysis) so dual-mode models like
|
|
244
|
+
// gemini-3.1-flash-image-preview can still perform text/structured
|
|
245
|
+
// generation — see its doc comment for the full precedence table.
|
|
246
|
+
const requestKind = resolveRequestKind(options, this.modelName);
|
|
247
|
+
if (requestKind === "image") {
|
|
249
248
|
logger.info(`Image model detected, forcing fake streaming`, {
|
|
250
249
|
provider: this.providerName,
|
|
251
250
|
model: this.modelName,
|
|
@@ -1066,14 +1065,13 @@ export class BaseProvider {
|
|
|
1066
1065
|
}
|
|
1067
1066
|
async runGenerateInActiveContext(options, startTime, otelSpan, otelSpanState) {
|
|
1068
1067
|
try {
|
|
1069
|
-
|
|
1068
|
+
// Single source of truth for "what kind of request is this" — see
|
|
1069
|
+
// resolveRequestKind's doc comment for the full precedence table.
|
|
1070
|
+
const requestKind = resolveRequestKind(options, this.modelName);
|
|
1071
|
+
if (requestKind === "video") {
|
|
1070
1072
|
return await this.handleVideoGeneration(options, startTime);
|
|
1071
1073
|
}
|
|
1072
|
-
|
|
1073
|
-
const requestsNonImageOutput = options.output?.format === "json" ||
|
|
1074
|
-
options.output?.format === "structured" ||
|
|
1075
|
-
options.output?.format === "text";
|
|
1076
|
-
if (isImageModel && !requestsNonImageOutput) {
|
|
1074
|
+
if (requestKind === "image") {
|
|
1077
1075
|
logger.info(`Image generation model detected, routing to executeImageGeneration`, {
|
|
1078
1076
|
provider: this.providerName,
|
|
1079
1077
|
model: this.modelName,
|
|
@@ -1081,7 +1079,7 @@ export class BaseProvider {
|
|
|
1081
1079
|
const imageResult = await this.executeImageGeneration(options);
|
|
1082
1080
|
return await this.enhanceResult(imageResult, options, startTime);
|
|
1083
1081
|
}
|
|
1084
|
-
if (
|
|
1082
|
+
if (requestKind === "tts-direct") {
|
|
1085
1083
|
return this.handleDirectTTSSynthesis(options, startTime);
|
|
1086
1084
|
}
|
|
1087
1085
|
const { tools, model } = await this.prepareGenerationContext(options);
|
|
@@ -2139,9 +2137,10 @@ export class BaseProvider {
|
|
|
2139
2137
|
}
|
|
2140
2138
|
// Get prompt text
|
|
2141
2139
|
const prompt = options.prompt || options.input?.text || "";
|
|
2142
|
-
// Honor output.video.provider — when omitted, fall back to
|
|
2143
|
-
//
|
|
2144
|
-
|
|
2140
|
+
// Honor output.video.provider — when omitted, fall back to the
|
|
2141
|
+
// catalog-derived default (currently "vertex") for backward
|
|
2142
|
+
// compatibility with the original implementation.
|
|
2143
|
+
const requestedProvider = options.output?.video?.provider ?? defaultProviderFor("video");
|
|
2145
2144
|
if (!VideoProcessor.supports(requestedProvider)) {
|
|
2146
2145
|
throw new VideoError({
|
|
2147
2146
|
code: VIDEO_ERROR_CODES.PROVIDER_NOT_SUPPORTED,
|
|
@@ -2177,7 +2176,12 @@ export class BaseProvider {
|
|
|
2177
2176
|
// shared timeout helper so standard video gen honors the caller's
|
|
2178
2177
|
// timeout the same way director mode does (see above ~Line 2062).
|
|
2179
2178
|
const videoTimeout = options.timeout ?? 600_000; // 10 min default
|
|
2180
|
-
const videoResult = await this.executeWithTimeout(() => VideoProcessor.generate(requestedProvider,
|
|
2179
|
+
const videoResult = await this.executeWithTimeout(() => VideoProcessor.generate(requestedProvider, {
|
|
2180
|
+
...(options.output?.video ?? {}),
|
|
2181
|
+
image: imageBuffer,
|
|
2182
|
+
prompt,
|
|
2183
|
+
region: options.region,
|
|
2184
|
+
}), { timeout: videoTimeout, operationType: "generate" });
|
|
2181
2185
|
// Prefer the handler's own model id (more accurate — it knows the exact
|
|
2182
2186
|
// checkpoint that ran). Fall back to the request-time value, and finally
|
|
2183
2187
|
// to the Vertex default only when we're on the Vertex route.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { RequestKind, RequestKindInput } from "../types/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* The dispatch decision for "what kind of request is this" — text, image,
|
|
4
|
+
* video, music, avatar, direct TTS synthesis, or PPT generation — at the
|
|
5
|
+
* CORE call sites: neurolink.ts's maybeHandleEarlyGenerateResult
|
|
6
|
+
* (music/avatar/ppt/workflow routing) and baseProvider.ts's
|
|
7
|
+
* stream()/runGenerateInActiveContext (image/video/tts-direct routing) call
|
|
8
|
+
* this instead of independently re-deriving the decision.
|
|
9
|
+
*
|
|
10
|
+
* NOT yet the only copy: replicate.ts's generate() override and
|
|
11
|
+
* googleVertex/client.ts's native dispatch (~6672-6718) still carry their
|
|
12
|
+
* own provider-internal versions — the Vertex one with a cruder
|
|
13
|
+
* startsWith() image match. Migrating those two is queued follow-up work;
|
|
14
|
+
* until it lands, an edit to this precedence table does not reach them.
|
|
15
|
+
*
|
|
16
|
+
* Precedence, checked in order:
|
|
17
|
+
* 1. output.mode (music/avatar/video/ppt) — an explicit mode always wins.
|
|
18
|
+
* 2. an image-generation model, unless the caller explicitly asked for a
|
|
19
|
+
* non-image output.format (json/structured/text) — this lets dual-mode
|
|
20
|
+
* models like gemini-3.1-flash-image-preview still perform text or
|
|
21
|
+
* structured generation when requested.
|
|
22
|
+
* 3. tts.enabled without tts.useAiResponse — direct synthesis, bypassing
|
|
23
|
+
* the LLM turn entirely (useAiResponse means the LLM's own text
|
|
24
|
+
* response gets synthesized afterward, which is NOT this branch).
|
|
25
|
+
* 4. otherwise, "text".
|
|
26
|
+
*/
|
|
27
|
+
export declare function resolveRequestKind(options: RequestKindInput, modelName?: string): RequestKind;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { isImageGenerationModel } from "./constants.js";
|
|
2
|
+
/**
|
|
3
|
+
* The dispatch decision for "what kind of request is this" — text, image,
|
|
4
|
+
* video, music, avatar, direct TTS synthesis, or PPT generation — at the
|
|
5
|
+
* CORE call sites: neurolink.ts's maybeHandleEarlyGenerateResult
|
|
6
|
+
* (music/avatar/ppt/workflow routing) and baseProvider.ts's
|
|
7
|
+
* stream()/runGenerateInActiveContext (image/video/tts-direct routing) call
|
|
8
|
+
* this instead of independently re-deriving the decision.
|
|
9
|
+
*
|
|
10
|
+
* NOT yet the only copy: replicate.ts's generate() override and
|
|
11
|
+
* googleVertex/client.ts's native dispatch (~6672-6718) still carry their
|
|
12
|
+
* own provider-internal versions — the Vertex one with a cruder
|
|
13
|
+
* startsWith() image match. Migrating those two is queued follow-up work;
|
|
14
|
+
* until it lands, an edit to this precedence table does not reach them.
|
|
15
|
+
*
|
|
16
|
+
* Precedence, checked in order:
|
|
17
|
+
* 1. output.mode (music/avatar/video/ppt) — an explicit mode always wins.
|
|
18
|
+
* 2. an image-generation model, unless the caller explicitly asked for a
|
|
19
|
+
* non-image output.format (json/structured/text) — this lets dual-mode
|
|
20
|
+
* models like gemini-3.1-flash-image-preview still perform text or
|
|
21
|
+
* structured generation when requested.
|
|
22
|
+
* 3. tts.enabled without tts.useAiResponse — direct synthesis, bypassing
|
|
23
|
+
* the LLM turn entirely (useAiResponse means the LLM's own text
|
|
24
|
+
* response gets synthesized afterward, which is NOT this branch).
|
|
25
|
+
* 4. otherwise, "text".
|
|
26
|
+
*/
|
|
27
|
+
export function resolveRequestKind(options, modelName) {
|
|
28
|
+
if (options.output?.mode === "music") {
|
|
29
|
+
return "music";
|
|
30
|
+
}
|
|
31
|
+
if (options.output?.mode === "avatar") {
|
|
32
|
+
return "avatar";
|
|
33
|
+
}
|
|
34
|
+
if (options.output?.mode === "video") {
|
|
35
|
+
return "video";
|
|
36
|
+
}
|
|
37
|
+
if (options.output?.mode === "ppt") {
|
|
38
|
+
return "ppt";
|
|
39
|
+
}
|
|
40
|
+
const requestsNonImageOutput = options.output?.format === "json" ||
|
|
41
|
+
options.output?.format === "structured" ||
|
|
42
|
+
options.output?.format === "text";
|
|
43
|
+
if (isImageGenerationModel(modelName) && !requestsNonImageOutput) {
|
|
44
|
+
return "image";
|
|
45
|
+
}
|
|
46
|
+
if (options.tts?.enabled && !options.tts?.useAiResponse) {
|
|
47
|
+
return "tts-direct";
|
|
48
|
+
}
|
|
49
|
+
return "text";
|
|
50
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { MediaHandlerDescriptor, MediaHandlerKind } from "../types/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Static catalog of every shipped media-handler provider, across all six
|
|
4
|
+
* ecosystems (TTS, STT, Realtime, Video, Avatar, Music). Pure data — no
|
|
5
|
+
* factory functions, no class imports — mirroring the
|
|
6
|
+
* src/lib/factories/providerDescriptors.ts pattern for text/image
|
|
7
|
+
* providers.
|
|
8
|
+
*
|
|
9
|
+
* Entries mirror providerRegistry.ts's hand-constructed TTS/STT/Realtime/
|
|
10
|
+
* Video/Avatar/Music registration blocks (registerAllProviders()) exactly —
|
|
11
|
+
* this file states today's truth, not an aspirational shape. Keep it in
|
|
12
|
+
* sync if those blocks change.
|
|
13
|
+
*/
|
|
14
|
+
export declare const MEDIA_HANDLER_CATALOG: readonly MediaHandlerDescriptor[];
|
|
15
|
+
/** Every selectable provider name for `kind`, primaries and aliases both. */
|
|
16
|
+
export declare function providerChoicesFor(kind: MediaHandlerKind): string[];
|
|
17
|
+
/** The first-listed primary provider name for `kind` — used as a fallback default. */
|
|
18
|
+
export declare function defaultProviderFor(kind: MediaHandlerKind): string;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Static catalog of every shipped media-handler provider, across all six
|
|
3
|
+
* ecosystems (TTS, STT, Realtime, Video, Avatar, Music). Pure data — no
|
|
4
|
+
* factory functions, no class imports — mirroring the
|
|
5
|
+
* src/lib/factories/providerDescriptors.ts pattern for text/image
|
|
6
|
+
* providers.
|
|
7
|
+
*
|
|
8
|
+
* Entries mirror providerRegistry.ts's hand-constructed TTS/STT/Realtime/
|
|
9
|
+
* Video/Avatar/Music registration blocks (registerAllProviders()) exactly —
|
|
10
|
+
* this file states today's truth, not an aspirational shape. Keep it in
|
|
11
|
+
* sync if those blocks change.
|
|
12
|
+
*/
|
|
13
|
+
export const MEDIA_HANDLER_CATALOG = [
|
|
14
|
+
// --- TTS ---
|
|
15
|
+
{ kind: "tts", name: "google-ai", aliases: ["vertex"] },
|
|
16
|
+
{ kind: "tts", name: "openai-tts" },
|
|
17
|
+
{ kind: "tts", name: "elevenlabs", aliases: ["elevenlabs-tts"] },
|
|
18
|
+
{ kind: "tts", name: "azure-tts" },
|
|
19
|
+
{ kind: "tts", name: "fish-audio" },
|
|
20
|
+
{ kind: "tts", name: "cartesia" },
|
|
21
|
+
// --- STT ---
|
|
22
|
+
{ kind: "stt", name: "whisper", aliases: ["openai-stt"] },
|
|
23
|
+
{ kind: "stt", name: "deepgram" },
|
|
24
|
+
{ kind: "stt", name: "google-stt" },
|
|
25
|
+
{ kind: "stt", name: "azure-stt" },
|
|
26
|
+
// --- Realtime ---
|
|
27
|
+
{ kind: "realtime", name: "openai-realtime" },
|
|
28
|
+
{ kind: "realtime", name: "gemini-live" },
|
|
29
|
+
// --- Video ---
|
|
30
|
+
{ kind: "video", name: "vertex" },
|
|
31
|
+
{ kind: "video", name: "kling" },
|
|
32
|
+
{ kind: "video", name: "runway" },
|
|
33
|
+
{ kind: "video", name: "replicate" },
|
|
34
|
+
// --- Avatar ---
|
|
35
|
+
{ kind: "avatar", name: "d-id" },
|
|
36
|
+
{ kind: "avatar", name: "replicate", aliases: ["musetalk"] },
|
|
37
|
+
{ kind: "avatar", name: "heygen" },
|
|
38
|
+
// --- Music ---
|
|
39
|
+
{ kind: "music", name: "beatoven" },
|
|
40
|
+
{ kind: "music", name: "replicate", aliases: ["musicgen"] },
|
|
41
|
+
{ kind: "music", name: "elevenlabs-music", aliases: ["elevenlabs-sound"] },
|
|
42
|
+
{ kind: "music", name: "lyria" },
|
|
43
|
+
];
|
|
44
|
+
/** Every selectable provider name for `kind`, primaries and aliases both. */
|
|
45
|
+
export function providerChoicesFor(kind) {
|
|
46
|
+
const choices = [];
|
|
47
|
+
for (const entry of MEDIA_HANDLER_CATALOG) {
|
|
48
|
+
if (entry.kind !== kind) {
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
choices.push(entry.name);
|
|
52
|
+
if (entry.aliases) {
|
|
53
|
+
choices.push(...entry.aliases);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return choices;
|
|
57
|
+
}
|
|
58
|
+
/** The first-listed primary provider name for `kind` — used as a fallback default. */
|
|
59
|
+
export function defaultProviderFor(kind) {
|
|
60
|
+
const first = MEDIA_HANDLER_CATALOG.find((entry) => entry.kind === kind);
|
|
61
|
+
if (!first) {
|
|
62
|
+
throw new Error(`No media handler catalog entries registered for kind "${kind}"`);
|
|
63
|
+
}
|
|
64
|
+
return first.name;
|
|
65
|
+
}
|