@juspay/neurolink 9.64.0 → 9.65.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/README.md +18 -17
- package/dist/adapters/providerImageAdapter.js +29 -1
- package/dist/adapters/replicate/auth.d.ts +19 -0
- package/dist/adapters/replicate/auth.js +32 -0
- package/dist/adapters/replicate/predictionLifecycle.d.ts +46 -0
- package/dist/adapters/replicate/predictionLifecycle.js +283 -0
- package/dist/adapters/video/klingVideoHandler.d.ts +37 -0
- package/dist/adapters/video/klingVideoHandler.js +305 -0
- package/dist/adapters/video/replicateVideoHandler.d.ts +29 -0
- package/dist/adapters/video/replicateVideoHandler.js +157 -0
- package/dist/adapters/video/runwayVideoHandler.d.ts +32 -0
- package/dist/adapters/video/runwayVideoHandler.js +316 -0
- package/dist/adapters/video/vertexVideoHandler.d.ts +19 -1
- package/dist/adapters/video/vertexVideoHandler.js +33 -9
- package/dist/autoresearch/runner.js +8 -2
- package/dist/avatar/index.d.ts +13 -0
- package/dist/avatar/index.js +13 -0
- package/dist/avatar/providers/DIDAvatar.d.ts +49 -0
- package/dist/avatar/providers/DIDAvatar.js +501 -0
- package/dist/avatar/providers/HeyGenAvatar.d.ts +30 -0
- package/dist/avatar/providers/HeyGenAvatar.js +337 -0
- package/dist/avatar/providers/ReplicateAvatar.d.ts +36 -0
- package/dist/avatar/providers/ReplicateAvatar.js +267 -0
- package/dist/browser/neurolink.min.js +633 -610
- package/dist/cli/commands/mcp.js +29 -0
- package/dist/cli/commands/proxy.js +24 -5
- package/dist/cli/factories/commandFactory.d.ts +11 -1
- package/dist/cli/factories/commandFactory.js +291 -38
- package/dist/constants/contextWindows.js +101 -0
- package/dist/constants/enums.d.ts +273 -2
- package/dist/constants/enums.js +290 -1
- package/dist/constants/videoErrors.d.ts +4 -0
- package/dist/constants/videoErrors.js +4 -0
- package/dist/core/baseProvider.d.ts +22 -2
- package/dist/core/baseProvider.js +217 -11
- package/dist/core/constants.d.ts +11 -0
- package/dist/core/constants.js +69 -1
- package/dist/core/redisConversationMemoryManager.js +6 -0
- package/dist/evaluation/index.d.ts +2 -0
- package/dist/evaluation/index.js +4 -0
- package/dist/factories/providerFactory.js +7 -1
- package/dist/factories/providerRegistry.js +202 -5
- package/dist/features/ppt/contentPlanner.js +42 -14
- package/dist/index.d.ts +9 -1
- package/dist/index.js +16 -1
- package/dist/lib/adapters/providerImageAdapter.js +29 -1
- package/dist/lib/adapters/replicate/auth.d.ts +19 -0
- package/dist/lib/adapters/replicate/auth.js +33 -0
- package/dist/lib/adapters/replicate/predictionLifecycle.d.ts +46 -0
- package/dist/lib/adapters/replicate/predictionLifecycle.js +284 -0
- package/dist/lib/adapters/video/klingVideoHandler.d.ts +37 -0
- package/dist/lib/adapters/video/klingVideoHandler.js +306 -0
- package/dist/lib/adapters/video/replicateVideoHandler.d.ts +29 -0
- package/dist/lib/adapters/video/replicateVideoHandler.js +158 -0
- package/dist/lib/adapters/video/runwayVideoHandler.d.ts +32 -0
- package/dist/lib/adapters/video/runwayVideoHandler.js +317 -0
- package/dist/lib/adapters/video/vertexVideoHandler.d.ts +19 -1
- package/dist/lib/adapters/video/vertexVideoHandler.js +33 -9
- package/dist/lib/autoresearch/runner.js +8 -2
- package/dist/lib/avatar/index.d.ts +13 -0
- package/dist/lib/avatar/index.js +14 -0
- package/dist/lib/avatar/providers/DIDAvatar.d.ts +49 -0
- package/dist/lib/avatar/providers/DIDAvatar.js +502 -0
- package/dist/lib/avatar/providers/HeyGenAvatar.d.ts +30 -0
- package/dist/lib/avatar/providers/HeyGenAvatar.js +338 -0
- package/dist/lib/avatar/providers/ReplicateAvatar.d.ts +36 -0
- package/dist/lib/avatar/providers/ReplicateAvatar.js +268 -0
- package/dist/lib/constants/contextWindows.js +101 -0
- package/dist/lib/constants/enums.d.ts +273 -2
- package/dist/lib/constants/enums.js +290 -1
- package/dist/lib/constants/videoErrors.d.ts +4 -0
- package/dist/lib/constants/videoErrors.js +4 -0
- package/dist/lib/core/baseProvider.d.ts +22 -2
- package/dist/lib/core/baseProvider.js +217 -11
- package/dist/lib/core/constants.d.ts +11 -0
- package/dist/lib/core/constants.js +69 -1
- package/dist/lib/core/redisConversationMemoryManager.js +6 -0
- package/dist/lib/evaluation/index.d.ts +2 -0
- package/dist/lib/evaluation/index.js +4 -0
- package/dist/lib/factories/providerFactory.js +7 -1
- package/dist/lib/factories/providerRegistry.js +202 -5
- package/dist/lib/features/ppt/contentPlanner.js +42 -14
- package/dist/lib/index.d.ts +9 -1
- package/dist/lib/index.js +16 -1
- package/dist/lib/middleware/builtin/lifecycle.js +39 -9
- package/dist/lib/music/index.d.ts +13 -0
- package/dist/lib/music/index.js +14 -0
- package/dist/lib/music/providers/BeatovenMusic.d.ts +31 -0
- package/dist/lib/music/providers/BeatovenMusic.js +334 -0
- package/dist/lib/music/providers/ElevenLabsMusic.d.ts +30 -0
- package/dist/lib/music/providers/ElevenLabsMusic.js +169 -0
- package/dist/lib/music/providers/LyriaMusic.d.ts +29 -0
- package/dist/lib/music/providers/LyriaMusic.js +173 -0
- package/dist/lib/music/providers/ReplicateMusic.d.ts +31 -0
- package/dist/lib/music/providers/ReplicateMusic.js +262 -0
- package/dist/lib/neurolink.d.ts +30 -0
- package/dist/lib/neurolink.js +323 -77
- package/dist/lib/providers/amazonBedrock.d.ts +10 -0
- package/dist/lib/providers/amazonBedrock.js +94 -39
- package/dist/lib/providers/anthropic.js +55 -7
- package/dist/lib/providers/anthropicBaseProvider.js +1 -1
- package/dist/lib/providers/azureOpenai.js +66 -17
- package/dist/lib/providers/cloudflare.d.ts +35 -0
- package/dist/lib/providers/cloudflare.js +174 -0
- package/dist/lib/providers/cohere.d.ts +52 -0
- package/dist/lib/providers/cohere.js +253 -0
- package/dist/lib/providers/deepseek.js +72 -17
- package/dist/lib/providers/fireworks.d.ts +33 -0
- package/dist/lib/providers/fireworks.js +164 -0
- package/dist/lib/providers/googleAiStudio.js +45 -6
- package/dist/lib/providers/googleNativeGemini3.d.ts +24 -1
- package/dist/lib/providers/googleNativeGemini3.js +173 -21
- package/dist/lib/providers/googleVertex.js +173 -17
- package/dist/lib/providers/groq.d.ts +33 -0
- package/dist/lib/providers/groq.js +181 -0
- package/dist/lib/providers/huggingFace.js +9 -8
- package/dist/lib/providers/ideogram.d.ts +34 -0
- package/dist/lib/providers/ideogram.js +184 -0
- package/dist/lib/providers/index.d.ts +13 -0
- package/dist/lib/providers/index.js +13 -0
- package/dist/lib/providers/jina.d.ts +59 -0
- package/dist/lib/providers/jina.js +218 -0
- package/dist/lib/providers/llamaCpp.js +14 -46
- package/dist/lib/providers/lmStudio.js +14 -47
- package/dist/lib/providers/mistral.js +7 -7
- package/dist/lib/providers/nvidiaNim.js +160 -19
- package/dist/lib/providers/ollama.js +7 -7
- package/dist/lib/providers/openAI.d.ts +22 -1
- package/dist/lib/providers/openAI.js +181 -0
- package/dist/lib/providers/openRouter.js +35 -23
- package/dist/lib/providers/openaiCompatible.js +9 -8
- package/dist/lib/providers/perplexity.d.ts +33 -0
- package/dist/lib/providers/perplexity.js +179 -0
- package/dist/lib/providers/recraft.d.ts +34 -0
- package/dist/lib/providers/recraft.js +197 -0
- package/dist/lib/providers/replicate.d.ts +75 -0
- package/dist/lib/providers/replicate.js +403 -0
- package/dist/lib/providers/stability.d.ts +37 -0
- package/dist/lib/providers/stability.js +191 -0
- package/dist/lib/providers/togetherAi.d.ts +33 -0
- package/dist/lib/providers/togetherAi.js +176 -0
- package/dist/lib/providers/voyage.d.ts +47 -0
- package/dist/lib/providers/voyage.js +177 -0
- package/dist/lib/providers/xai.d.ts +33 -0
- package/dist/lib/providers/xai.js +172 -0
- package/dist/lib/telemetry/index.d.ts +1 -1
- package/dist/lib/telemetry/index.js +1 -1
- package/dist/lib/telemetry/tracers.d.ts +19 -0
- package/dist/lib/telemetry/tracers.js +19 -0
- package/dist/lib/telemetry/withSpan.d.ts +35 -0
- package/dist/lib/telemetry/withSpan.js +103 -0
- package/dist/lib/types/avatar.d.ts +143 -0
- package/dist/lib/types/avatar.js +20 -0
- package/dist/lib/types/cli.d.ts +6 -0
- package/dist/lib/types/generate.d.ts +62 -5
- package/dist/lib/types/index.d.ts +5 -0
- package/dist/lib/types/index.js +7 -0
- package/dist/lib/types/middleware.d.ts +27 -0
- package/dist/lib/types/multimodal.d.ts +35 -2
- package/dist/lib/types/music.d.ts +165 -0
- package/dist/lib/types/music.js +21 -0
- package/dist/lib/types/providers.d.ts +144 -1
- package/dist/lib/types/replicate.d.ts +67 -0
- package/dist/lib/types/replicate.js +10 -0
- package/dist/lib/types/safeFetch.d.ts +15 -0
- package/dist/lib/types/safeFetch.js +7 -0
- package/dist/lib/types/stream.d.ts +2 -1
- package/dist/lib/types/tools.d.ts +13 -0
- package/dist/lib/types/video.d.ts +89 -0
- package/dist/lib/types/video.js +15 -0
- package/dist/lib/utils/avatarProcessor.d.ts +68 -0
- package/dist/lib/utils/avatarProcessor.js +172 -0
- package/dist/lib/utils/cloneOptions.d.ts +36 -0
- package/dist/lib/utils/cloneOptions.js +62 -0
- package/dist/lib/utils/lifecycleCallbacks.d.ts +51 -8
- package/dist/lib/utils/lifecycleCallbacks.js +82 -26
- package/dist/lib/utils/lifecycleTimeout.d.ts +25 -0
- package/dist/lib/utils/lifecycleTimeout.js +39 -0
- package/dist/lib/utils/logSanitize.d.ts +49 -0
- package/dist/lib/utils/logSanitize.js +170 -0
- package/dist/lib/utils/loggingFetch.d.ts +29 -0
- package/dist/lib/utils/loggingFetch.js +60 -0
- package/dist/lib/utils/messageBuilder.js +43 -25
- package/dist/lib/utils/modelChoices.js +236 -3
- package/dist/lib/utils/musicProcessor.d.ts +67 -0
- package/dist/lib/utils/musicProcessor.js +189 -0
- package/dist/lib/utils/optionsConversion.js +3 -2
- package/dist/lib/utils/parameterValidation.js +14 -4
- package/dist/lib/utils/pricing.js +193 -0
- package/dist/lib/utils/providerConfig.d.ts +55 -0
- package/dist/lib/utils/providerConfig.js +224 -0
- package/dist/lib/utils/safeFetch.d.ts +26 -0
- package/dist/lib/utils/safeFetch.js +83 -0
- package/dist/lib/utils/sizeGuard.d.ts +34 -0
- package/dist/lib/utils/sizeGuard.js +45 -0
- package/dist/lib/utils/ssrfGuard.d.ts +52 -0
- package/dist/lib/utils/ssrfGuard.js +411 -0
- package/dist/lib/utils/videoProcessor.d.ts +60 -0
- package/dist/lib/utils/videoProcessor.js +201 -0
- package/dist/lib/voice/providers/FishAudioTTS.d.ts +27 -0
- package/dist/lib/voice/providers/FishAudioTTS.js +183 -0
- package/dist/lib/workflow/core/ensembleExecutor.js +26 -9
- package/dist/middleware/builtin/lifecycle.js +39 -9
- package/dist/music/index.d.ts +13 -0
- package/dist/music/index.js +13 -0
- package/dist/music/providers/BeatovenMusic.d.ts +31 -0
- package/dist/music/providers/BeatovenMusic.js +333 -0
- package/dist/music/providers/ElevenLabsMusic.d.ts +30 -0
- package/dist/music/providers/ElevenLabsMusic.js +168 -0
- package/dist/music/providers/LyriaMusic.d.ts +29 -0
- package/dist/music/providers/LyriaMusic.js +172 -0
- package/dist/music/providers/ReplicateMusic.d.ts +31 -0
- package/dist/music/providers/ReplicateMusic.js +261 -0
- package/dist/neurolink.d.ts +30 -0
- package/dist/neurolink.js +323 -77
- package/dist/providers/amazonBedrock.d.ts +10 -0
- package/dist/providers/amazonBedrock.js +94 -39
- package/dist/providers/anthropic.js +55 -7
- package/dist/providers/anthropicBaseProvider.js +1 -1
- package/dist/providers/azureOpenai.js +66 -17
- package/dist/providers/cloudflare.d.ts +35 -0
- package/dist/providers/cloudflare.js +173 -0
- package/dist/providers/cohere.d.ts +52 -0
- package/dist/providers/cohere.js +252 -0
- package/dist/providers/deepseek.js +72 -17
- package/dist/providers/fireworks.d.ts +33 -0
- package/dist/providers/fireworks.js +163 -0
- package/dist/providers/googleAiStudio.js +45 -6
- package/dist/providers/googleNativeGemini3.d.ts +24 -1
- package/dist/providers/googleNativeGemini3.js +173 -21
- package/dist/providers/googleVertex.js +173 -17
- package/dist/providers/groq.d.ts +33 -0
- package/dist/providers/groq.js +180 -0
- package/dist/providers/huggingFace.js +9 -8
- package/dist/providers/ideogram.d.ts +34 -0
- package/dist/providers/ideogram.js +183 -0
- package/dist/providers/index.d.ts +13 -0
- package/dist/providers/index.js +13 -0
- package/dist/providers/jina.d.ts +59 -0
- package/dist/providers/jina.js +217 -0
- package/dist/providers/llamaCpp.js +14 -46
- package/dist/providers/lmStudio.js +14 -47
- package/dist/providers/mistral.js +7 -7
- package/dist/providers/nvidiaNim.js +160 -19
- package/dist/providers/ollama.js +7 -7
- package/dist/providers/openAI.d.ts +22 -1
- package/dist/providers/openAI.js +181 -0
- package/dist/providers/openRouter.js +35 -23
- package/dist/providers/openaiCompatible.js +9 -8
- package/dist/providers/perplexity.d.ts +33 -0
- package/dist/providers/perplexity.js +178 -0
- package/dist/providers/recraft.d.ts +34 -0
- package/dist/providers/recraft.js +196 -0
- package/dist/providers/replicate.d.ts +75 -0
- package/dist/providers/replicate.js +402 -0
- package/dist/providers/stability.d.ts +37 -0
- package/dist/providers/stability.js +190 -0
- package/dist/providers/togetherAi.d.ts +33 -0
- package/dist/providers/togetherAi.js +175 -0
- package/dist/providers/voyage.d.ts +47 -0
- package/dist/providers/voyage.js +176 -0
- package/dist/providers/xai.d.ts +33 -0
- package/dist/providers/xai.js +171 -0
- package/dist/telemetry/index.d.ts +1 -1
- package/dist/telemetry/index.js +1 -1
- package/dist/telemetry/tracers.d.ts +19 -0
- package/dist/telemetry/tracers.js +19 -0
- package/dist/telemetry/withSpan.d.ts +35 -0
- package/dist/telemetry/withSpan.js +103 -0
- package/dist/types/avatar.d.ts +143 -0
- package/dist/types/avatar.js +19 -0
- package/dist/types/cli.d.ts +6 -0
- package/dist/types/generate.d.ts +62 -5
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.js +7 -0
- package/dist/types/middleware.d.ts +27 -0
- package/dist/types/multimodal.d.ts +35 -2
- package/dist/types/music.d.ts +165 -0
- package/dist/types/music.js +20 -0
- package/dist/types/providers.d.ts +144 -1
- package/dist/types/replicate.d.ts +67 -0
- package/dist/types/replicate.js +9 -0
- package/dist/types/safeFetch.d.ts +15 -0
- package/dist/types/safeFetch.js +6 -0
- package/dist/types/stream.d.ts +2 -1
- package/dist/types/tools.d.ts +13 -0
- package/dist/types/video.d.ts +89 -0
- package/dist/types/video.js +14 -0
- package/dist/utils/avatarProcessor.d.ts +68 -0
- package/dist/utils/avatarProcessor.js +171 -0
- package/dist/utils/cloneOptions.d.ts +36 -0
- package/dist/utils/cloneOptions.js +61 -0
- package/dist/utils/lifecycleCallbacks.d.ts +51 -8
- package/dist/utils/lifecycleCallbacks.js +82 -26
- package/dist/utils/lifecycleTimeout.d.ts +25 -0
- package/dist/utils/lifecycleTimeout.js +38 -0
- package/dist/utils/logSanitize.d.ts +49 -0
- package/dist/utils/logSanitize.js +169 -0
- package/dist/utils/loggingFetch.d.ts +29 -0
- package/dist/utils/loggingFetch.js +59 -0
- package/dist/utils/messageBuilder.js +43 -25
- package/dist/utils/modelChoices.js +236 -3
- package/dist/utils/musicProcessor.d.ts +67 -0
- package/dist/utils/musicProcessor.js +188 -0
- package/dist/utils/optionsConversion.js +3 -2
- package/dist/utils/parameterValidation.js +14 -4
- package/dist/utils/pricing.js +193 -0
- package/dist/utils/providerConfig.d.ts +55 -0
- package/dist/utils/providerConfig.js +224 -0
- package/dist/utils/safeFetch.d.ts +26 -0
- package/dist/utils/safeFetch.js +82 -0
- package/dist/utils/sizeGuard.d.ts +34 -0
- package/dist/utils/sizeGuard.js +44 -0
- package/dist/utils/ssrfGuard.d.ts +52 -0
- package/dist/utils/ssrfGuard.js +410 -0
- package/dist/utils/videoProcessor.d.ts +60 -0
- package/dist/utils/videoProcessor.js +200 -0
- package/dist/voice/providers/FishAudioTTS.d.ts +27 -0
- package/dist/voice/providers/FishAudioTTS.js +182 -0
- package/dist/workflow/core/ensembleExecutor.js +26 -9
- package/package.json +32 -5
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Google Lyria 3 Pro Music Handler
|
|
3
|
+
*
|
|
4
|
+
* Synchronous generation against the Generative Language API. Returns
|
|
5
|
+
* audio inline as base64 in the response.
|
|
6
|
+
*
|
|
7
|
+
* @module music/providers/LyriaMusic
|
|
8
|
+
* @see https://ai.google.dev/gemini-api/docs/music-generation
|
|
9
|
+
*/
|
|
10
|
+
import { ErrorCategory, ErrorSeverity } from "../../constants/enums.js";
|
|
11
|
+
import { MUSIC_ERROR_CODES, MusicError } from "../../utils/musicProcessor.js";
|
|
12
|
+
import { logger } from "../../utils/logger.js";
|
|
13
|
+
import { sanitizeForLog } from "../../utils/logSanitize.js";
|
|
14
|
+
const DEFAULT_BASE_URL = "https://generativelanguage.googleapis.com/v1beta";
|
|
15
|
+
const DEFAULT_MODEL = "lyria-3-pro-preview";
|
|
16
|
+
const REQUEST_TIMEOUT_MS = 120_000;
|
|
17
|
+
/**
|
|
18
|
+
* Google Lyria 3 Pro Music Handler.
|
|
19
|
+
*
|
|
20
|
+
* Auth: `Authorization: Bearer ${GOOGLE_API_KEY}` or query-string
|
|
21
|
+
* `?key=${GOOGLE_API_KEY}` (the latter is more compatible with the
|
|
22
|
+
* Generative Language endpoints today).
|
|
23
|
+
*/
|
|
24
|
+
export class LyriaMusic {
|
|
25
|
+
maxDurationSeconds = 30;
|
|
26
|
+
supportedFormats = ["wav"];
|
|
27
|
+
supportedGenres = [
|
|
28
|
+
"ambient",
|
|
29
|
+
"classical",
|
|
30
|
+
"electronic",
|
|
31
|
+
"jazz",
|
|
32
|
+
"rock",
|
|
33
|
+
"pop",
|
|
34
|
+
"lo-fi",
|
|
35
|
+
"cinematic",
|
|
36
|
+
"orchestral",
|
|
37
|
+
"world",
|
|
38
|
+
];
|
|
39
|
+
apiKey;
|
|
40
|
+
baseUrl;
|
|
41
|
+
model;
|
|
42
|
+
constructor(apiKey) {
|
|
43
|
+
const resolved = (apiKey ??
|
|
44
|
+
process.env.GOOGLE_AI_LYRIA_API_KEY ??
|
|
45
|
+
process.env.GOOGLE_API_KEY ??
|
|
46
|
+
process.env.GOOGLE_AI_API_KEY ??
|
|
47
|
+
process.env.GEMINI_API_KEY ??
|
|
48
|
+
"").trim();
|
|
49
|
+
this.apiKey = resolved.length > 0 ? resolved : null;
|
|
50
|
+
this.baseUrl = (process.env.LYRIA_BASE_URL ?? DEFAULT_BASE_URL).replace(/\/$/, "");
|
|
51
|
+
this.model = process.env.LYRIA_MODEL ?? DEFAULT_MODEL;
|
|
52
|
+
}
|
|
53
|
+
isConfigured() {
|
|
54
|
+
return this.apiKey !== null;
|
|
55
|
+
}
|
|
56
|
+
async generate(options) {
|
|
57
|
+
if (!this.apiKey) {
|
|
58
|
+
throw new MusicError({
|
|
59
|
+
code: MUSIC_ERROR_CODES.PROVIDER_NOT_CONFIGURED,
|
|
60
|
+
message: "Lyria requires one of: GOOGLE_API_KEY, GOOGLE_AI_LYRIA_API_KEY, GOOGLE_AI_API_KEY, or GEMINI_API_KEY",
|
|
61
|
+
category: ErrorCategory.CONFIGURATION,
|
|
62
|
+
severity: ErrorSeverity.HIGH,
|
|
63
|
+
retriable: false,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
const startTime = Date.now();
|
|
67
|
+
const duration = Math.min(options.duration ?? 16, this.maxDurationSeconds);
|
|
68
|
+
// Lyria API no longer accepts `audioGenerationOptions` — duration is
|
|
69
|
+
// controlled implicitly by the prompt/model. Only `responseModalities`
|
|
70
|
+
// is allowed under `generationConfig`. Embed duration in the prompt
|
|
71
|
+
// so the model still gets the hint.
|
|
72
|
+
const promptWithDuration = `${this.buildPrompt(options)}. Duration: ${duration} seconds`;
|
|
73
|
+
const body = {
|
|
74
|
+
contents: [
|
|
75
|
+
{
|
|
76
|
+
parts: [
|
|
77
|
+
{
|
|
78
|
+
text: promptWithDuration,
|
|
79
|
+
},
|
|
80
|
+
],
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
generationConfig: {
|
|
84
|
+
responseModalities: ["AUDIO"],
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
const controller = new AbortController();
|
|
88
|
+
const timeoutId = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
89
|
+
let response;
|
|
90
|
+
try {
|
|
91
|
+
response = await fetch(`${this.baseUrl}/models/${this.model}:generateContent?key=${this.apiKey}`, {
|
|
92
|
+
method: "POST",
|
|
93
|
+
headers: {
|
|
94
|
+
"Content-Type": "application/json",
|
|
95
|
+
},
|
|
96
|
+
body: JSON.stringify(body),
|
|
97
|
+
signal: controller.signal,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
101
|
+
if (err instanceof Error && err.name === "AbortError") {
|
|
102
|
+
throw new MusicError({
|
|
103
|
+
code: MUSIC_ERROR_CODES.GENERATION_FAILED,
|
|
104
|
+
message: `Lyria request timed out after ${REQUEST_TIMEOUT_MS / 1000}s`,
|
|
105
|
+
category: ErrorCategory.NETWORK,
|
|
106
|
+
severity: ErrorSeverity.HIGH,
|
|
107
|
+
retriable: true,
|
|
108
|
+
originalError: err,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
throw err;
|
|
112
|
+
}
|
|
113
|
+
finally {
|
|
114
|
+
clearTimeout(timeoutId);
|
|
115
|
+
}
|
|
116
|
+
if (!response.ok) {
|
|
117
|
+
const rawText = await response.text();
|
|
118
|
+
const retriable = response.status === 408 ||
|
|
119
|
+
response.status === 429 ||
|
|
120
|
+
response.status >= 500;
|
|
121
|
+
throw new MusicError({
|
|
122
|
+
code: MUSIC_ERROR_CODES.GENERATION_FAILED,
|
|
123
|
+
message: `Lyria generation failed: ${response.status} — ${sanitizeForLog(rawText)}`,
|
|
124
|
+
category: retriable ? ErrorCategory.NETWORK : ErrorCategory.EXECUTION,
|
|
125
|
+
severity: ErrorSeverity.HIGH,
|
|
126
|
+
retriable,
|
|
127
|
+
context: { status: response.status },
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
const data = (await response.json());
|
|
131
|
+
const audioPart = data.candidates?.[0]?.content?.parts?.find((p) => p.inlineData?.mimeType?.startsWith("audio/"));
|
|
132
|
+
if (!audioPart?.inlineData?.data) {
|
|
133
|
+
throw new MusicError({
|
|
134
|
+
code: MUSIC_ERROR_CODES.GENERATION_FAILED,
|
|
135
|
+
message: "Lyria response missing audio data",
|
|
136
|
+
category: ErrorCategory.EXECUTION,
|
|
137
|
+
severity: ErrorSeverity.HIGH,
|
|
138
|
+
retriable: false,
|
|
139
|
+
context: { response: data },
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
const buffer = Buffer.from(audioPart.inlineData.data, "base64");
|
|
143
|
+
const latency = Date.now() - startTime;
|
|
144
|
+
logger.info(`[LyriaMusic] Generated ${buffer.length} bytes in ${latency}ms — model ${this.model}`);
|
|
145
|
+
return {
|
|
146
|
+
buffer,
|
|
147
|
+
format: "wav",
|
|
148
|
+
size: buffer.length,
|
|
149
|
+
duration,
|
|
150
|
+
provider: "lyria",
|
|
151
|
+
metadata: {
|
|
152
|
+
latency,
|
|
153
|
+
provider: "lyria",
|
|
154
|
+
model: this.model,
|
|
155
|
+
sampleRate: 48_000,
|
|
156
|
+
},
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
buildPrompt(options) {
|
|
160
|
+
const parts = [options.prompt];
|
|
161
|
+
if (options.genre) {
|
|
162
|
+
parts.push(`Genre: ${options.genre}`);
|
|
163
|
+
}
|
|
164
|
+
if (options.mood) {
|
|
165
|
+
parts.push(`Mood: ${options.mood}`);
|
|
166
|
+
}
|
|
167
|
+
if (options.tempo !== undefined) {
|
|
168
|
+
parts.push(`${options.tempo} BPM`);
|
|
169
|
+
}
|
|
170
|
+
return parts.join(". ");
|
|
171
|
+
}
|
|
172
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Replicate Music Handler (MusicGen default)
|
|
3
|
+
*
|
|
4
|
+
* Routes music generation through Replicate's universal prediction
|
|
5
|
+
* lifecycle. Default model is Meta's MusicGen; alternatives include
|
|
6
|
+
* Riffusion, AudioGen, and AudioLDM via `options.model`.
|
|
7
|
+
*
|
|
8
|
+
* @module music/providers/ReplicateMusic
|
|
9
|
+
* @see https://replicate.com/meta/musicgen
|
|
10
|
+
*/
|
|
11
|
+
import type { MusicAudioFormat, MusicHandler, MusicOptions, MusicResult } from "../../types/index.js";
|
|
12
|
+
export declare class ReplicateMusic implements MusicHandler {
|
|
13
|
+
readonly maxDurationSeconds = 30;
|
|
14
|
+
readonly supportedFormats: readonly MusicAudioFormat[];
|
|
15
|
+
readonly supportedGenres: readonly string[];
|
|
16
|
+
isConfigured(): boolean;
|
|
17
|
+
generate(options: MusicOptions): Promise<MusicResult>;
|
|
18
|
+
private buildPrompt;
|
|
19
|
+
private resolveBuffer;
|
|
20
|
+
/**
|
|
21
|
+
* Detect audio MIME subtype from magic bytes.
|
|
22
|
+
*
|
|
23
|
+
* - WAV : "RIFF" header (52 49 46 46)
|
|
24
|
+
* - MP3 : ID3 tag (49 44 33) or MPEG sync word 0xFF 0xEx
|
|
25
|
+
* - OGG : "OggS" capture pattern (4F 67 67 53)
|
|
26
|
+
* - M4A : "ftyp" box at offset 4
|
|
27
|
+
*
|
|
28
|
+
* Falls back to "mp3" when detection is inconclusive.
|
|
29
|
+
*/
|
|
30
|
+
private detectAudioType;
|
|
31
|
+
}
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Replicate Music Handler (MusicGen default)
|
|
3
|
+
*
|
|
4
|
+
* Routes music generation through Replicate's universal prediction
|
|
5
|
+
* lifecycle. Default model is Meta's MusicGen; alternatives include
|
|
6
|
+
* Riffusion, AudioGen, and AudioLDM via `options.model`.
|
|
7
|
+
*
|
|
8
|
+
* @module music/providers/ReplicateMusic
|
|
9
|
+
* @see https://replicate.com/meta/musicgen
|
|
10
|
+
*/
|
|
11
|
+
import { ErrorCategory, ErrorSeverity } from "../../constants/enums.js";
|
|
12
|
+
import { MUSIC_ERROR_CODES, MusicError } from "../../utils/musicProcessor.js";
|
|
13
|
+
import { logger } from "../../utils/logger.js";
|
|
14
|
+
import { getReplicateAuth } from "../../adapters/replicate/auth.js";
|
|
15
|
+
import { downloadPredictionOutput, predict, } from "../../adapters/replicate/predictionLifecycle.js";
|
|
16
|
+
import { MAX_AUDIO_BYTES, readBoundedBuffer } from "../../utils/sizeGuard.js";
|
|
17
|
+
import { assertSafeUrl } from "../../utils/ssrfGuard.js";
|
|
18
|
+
const DEFAULT_MODEL = "meta/musicgen:7be0f12c54a8d033a0fbd14418c9af98962da9a86f5ff7811f9b3423a1f0b7d7";
|
|
19
|
+
export class ReplicateMusic {
|
|
20
|
+
maxDurationSeconds = 30;
|
|
21
|
+
supportedFormats = [
|
|
22
|
+
"mp3",
|
|
23
|
+
"wav",
|
|
24
|
+
];
|
|
25
|
+
supportedGenres = [
|
|
26
|
+
"ambient",
|
|
27
|
+
"classical",
|
|
28
|
+
"electronic",
|
|
29
|
+
"rock",
|
|
30
|
+
"jazz",
|
|
31
|
+
"hip-hop",
|
|
32
|
+
"pop",
|
|
33
|
+
"lo-fi",
|
|
34
|
+
"cinematic",
|
|
35
|
+
"orchestral",
|
|
36
|
+
];
|
|
37
|
+
isConfigured() {
|
|
38
|
+
return getReplicateAuth() !== null;
|
|
39
|
+
}
|
|
40
|
+
async generate(options) {
|
|
41
|
+
const auth = getReplicateAuth();
|
|
42
|
+
if (!auth) {
|
|
43
|
+
throw new MusicError({
|
|
44
|
+
code: MUSIC_ERROR_CODES.PROVIDER_NOT_CONFIGURED,
|
|
45
|
+
message: "REPLICATE_API_TOKEN not configured",
|
|
46
|
+
category: ErrorCategory.CONFIGURATION,
|
|
47
|
+
severity: ErrorSeverity.HIGH,
|
|
48
|
+
retriable: false,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
const startTime = Date.now();
|
|
52
|
+
const model = options.model ?? DEFAULT_MODEL;
|
|
53
|
+
const requestedFormat = options.format ?? "mp3";
|
|
54
|
+
const upstreamFormat = this.supportedFormats.includes(requestedFormat)
|
|
55
|
+
? requestedFormat
|
|
56
|
+
: "mp3";
|
|
57
|
+
// Clamp to provider max and apply default; store as `effectiveDuration`
|
|
58
|
+
// so the returned result always reflects the audio that was actually generated.
|
|
59
|
+
const effectiveDuration = Math.min(options.duration ?? 8, this.maxDurationSeconds);
|
|
60
|
+
// MusicGen accepts these inputs; other models override via cast.
|
|
61
|
+
const inputPayload = {
|
|
62
|
+
prompt: this.buildPrompt(options),
|
|
63
|
+
duration: effectiveDuration,
|
|
64
|
+
output_format: upstreamFormat,
|
|
65
|
+
model_version: "stereo-large",
|
|
66
|
+
normalization_strategy: "loudness",
|
|
67
|
+
};
|
|
68
|
+
if (options.tempo !== undefined) {
|
|
69
|
+
inputPayload.bpm = options.tempo;
|
|
70
|
+
}
|
|
71
|
+
if (options.referenceAudio) {
|
|
72
|
+
const ref = await this.resolveBuffer(options.referenceAudio);
|
|
73
|
+
inputPayload.input_audio = `data:audio/${this.detectAudioType(ref)};base64,${ref.toString("base64")}`;
|
|
74
|
+
}
|
|
75
|
+
let prediction;
|
|
76
|
+
try {
|
|
77
|
+
prediction = await predict(auth, { model, input: inputPayload });
|
|
78
|
+
}
|
|
79
|
+
catch (err) {
|
|
80
|
+
throw new MusicError({
|
|
81
|
+
code: MUSIC_ERROR_CODES.GENERATION_FAILED,
|
|
82
|
+
message: `Replicate music generation failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
83
|
+
category: ErrorCategory.EXECUTION,
|
|
84
|
+
severity: ErrorSeverity.HIGH,
|
|
85
|
+
retriable: true,
|
|
86
|
+
// Sanitize context: omit raw `options` which may contain large Buffers
|
|
87
|
+
// (referenceAudio) and arbitrary user content.
|
|
88
|
+
context: {
|
|
89
|
+
model,
|
|
90
|
+
duration: effectiveDuration,
|
|
91
|
+
format: upstreamFormat,
|
|
92
|
+
hasReferenceAudio: options.referenceAudio !== undefined,
|
|
93
|
+
},
|
|
94
|
+
originalError: err instanceof Error ? err : undefined,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
let buffer;
|
|
98
|
+
try {
|
|
99
|
+
buffer = await downloadPredictionOutput(prediction, MAX_AUDIO_BYTES);
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
throw new MusicError({
|
|
103
|
+
code: MUSIC_ERROR_CODES.GENERATION_FAILED,
|
|
104
|
+
message: `Replicate music download failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
105
|
+
category: ErrorCategory.NETWORK,
|
|
106
|
+
severity: ErrorSeverity.MEDIUM,
|
|
107
|
+
retriable: true,
|
|
108
|
+
context: { predictionId: prediction.id },
|
|
109
|
+
originalError: err instanceof Error ? err : undefined,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
const latency = Date.now() - startTime;
|
|
113
|
+
logger.info(`[ReplicateMusic] Generated ${buffer.length} bytes in ${latency}ms — model ${model}`);
|
|
114
|
+
return {
|
|
115
|
+
buffer,
|
|
116
|
+
format: upstreamFormat,
|
|
117
|
+
size: buffer.length,
|
|
118
|
+
// Return the clamped/defaulted duration actually sent to the model,
|
|
119
|
+
// not the raw options.duration which may have been out of bounds or undefined.
|
|
120
|
+
duration: effectiveDuration,
|
|
121
|
+
provider: "replicate",
|
|
122
|
+
metadata: {
|
|
123
|
+
latency,
|
|
124
|
+
provider: "replicate",
|
|
125
|
+
model,
|
|
126
|
+
jobId: prediction.id,
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
buildPrompt(options) {
|
|
131
|
+
const parts = [options.prompt];
|
|
132
|
+
if (options.genre) {
|
|
133
|
+
parts.push(`Genre: ${options.genre}`);
|
|
134
|
+
}
|
|
135
|
+
if (options.mood) {
|
|
136
|
+
parts.push(`Mood: ${options.mood}`);
|
|
137
|
+
}
|
|
138
|
+
if (options.tempo !== undefined) {
|
|
139
|
+
parts.push(`${options.tempo} BPM`);
|
|
140
|
+
}
|
|
141
|
+
return parts.join(". ");
|
|
142
|
+
}
|
|
143
|
+
async resolveBuffer(input) {
|
|
144
|
+
if (Buffer.isBuffer(input)) {
|
|
145
|
+
return input;
|
|
146
|
+
}
|
|
147
|
+
// Reject local file paths — only Buffer or HTTPS URLs are accepted.
|
|
148
|
+
if (!/^https:\/\//.test(input)) {
|
|
149
|
+
throw new MusicError({
|
|
150
|
+
code: MUSIC_ERROR_CODES.INVALID_INPUT,
|
|
151
|
+
message: `Invalid input: expected Buffer or HTTPS URL, got string "${input}". Local file reads are not supported.`,
|
|
152
|
+
category: ErrorCategory.VALIDATION,
|
|
153
|
+
severity: ErrorSeverity.HIGH,
|
|
154
|
+
retriable: false,
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
try {
|
|
158
|
+
await assertSafeUrl(input);
|
|
159
|
+
}
|
|
160
|
+
catch (err) {
|
|
161
|
+
throw new MusicError({
|
|
162
|
+
code: MUSIC_ERROR_CODES.INVALID_INPUT,
|
|
163
|
+
message: `Unsafe URL rejected: ${err instanceof Error ? err.message : String(err)}`,
|
|
164
|
+
category: ErrorCategory.VALIDATION,
|
|
165
|
+
severity: ErrorSeverity.HIGH,
|
|
166
|
+
retriable: false,
|
|
167
|
+
context: { url: input },
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
const FETCH_TIMEOUT_MS = 60_000;
|
|
171
|
+
const controller = new AbortController();
|
|
172
|
+
const timeoutId = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
|
|
173
|
+
let r;
|
|
174
|
+
try {
|
|
175
|
+
r = await fetch(input, { signal: controller.signal });
|
|
176
|
+
}
|
|
177
|
+
catch (err) {
|
|
178
|
+
if (err instanceof Error && err.name === "AbortError") {
|
|
179
|
+
throw new MusicError({
|
|
180
|
+
code: MUSIC_ERROR_CODES.GENERATION_FAILED,
|
|
181
|
+
message: `Replicate music reference-audio fetch timed out after ${FETCH_TIMEOUT_MS / 1000}s: ${input}`,
|
|
182
|
+
category: ErrorCategory.NETWORK,
|
|
183
|
+
severity: ErrorSeverity.MEDIUM,
|
|
184
|
+
retriable: true,
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
throw err;
|
|
188
|
+
}
|
|
189
|
+
finally {
|
|
190
|
+
clearTimeout(timeoutId);
|
|
191
|
+
}
|
|
192
|
+
if (!r.ok) {
|
|
193
|
+
throw new MusicError({
|
|
194
|
+
code: MUSIC_ERROR_CODES.GENERATION_FAILED,
|
|
195
|
+
message: `Failed to fetch reference audio: ${input}: ${r.status}`,
|
|
196
|
+
category: ErrorCategory.NETWORK,
|
|
197
|
+
severity: ErrorSeverity.MEDIUM,
|
|
198
|
+
retriable: r.status >= 500,
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
try {
|
|
202
|
+
return await readBoundedBuffer(r, MAX_AUDIO_BYTES, "Replicate reference audio");
|
|
203
|
+
}
|
|
204
|
+
catch (err) {
|
|
205
|
+
throw new MusicError({
|
|
206
|
+
code: MUSIC_ERROR_CODES.INVALID_INPUT,
|
|
207
|
+
message: `Replicate reference audio too large: ${err instanceof Error ? err.message : String(err)}`,
|
|
208
|
+
category: ErrorCategory.VALIDATION,
|
|
209
|
+
severity: ErrorSeverity.HIGH,
|
|
210
|
+
retriable: false,
|
|
211
|
+
context: { url: input },
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Detect audio MIME subtype from magic bytes.
|
|
217
|
+
*
|
|
218
|
+
* - WAV : "RIFF" header (52 49 46 46)
|
|
219
|
+
* - MP3 : ID3 tag (49 44 33) or MPEG sync word 0xFF 0xEx
|
|
220
|
+
* - OGG : "OggS" capture pattern (4F 67 67 53)
|
|
221
|
+
* - M4A : "ftyp" box at offset 4
|
|
222
|
+
*
|
|
223
|
+
* Falls back to "mp3" when detection is inconclusive.
|
|
224
|
+
*/
|
|
225
|
+
detectAudioType(buffer) {
|
|
226
|
+
if (buffer.length < 4) {
|
|
227
|
+
return "mp3";
|
|
228
|
+
}
|
|
229
|
+
// WAV: starts with RIFF
|
|
230
|
+
if (buffer[0] === 0x52 &&
|
|
231
|
+
buffer[1] === 0x49 &&
|
|
232
|
+
buffer[2] === 0x46 &&
|
|
233
|
+
buffer[3] === 0x46) {
|
|
234
|
+
return "wav";
|
|
235
|
+
}
|
|
236
|
+
// OGG: starts with OggS
|
|
237
|
+
if (buffer[0] === 0x4f &&
|
|
238
|
+
buffer[1] === 0x67 &&
|
|
239
|
+
buffer[2] === 0x67 &&
|
|
240
|
+
buffer[3] === 0x53) {
|
|
241
|
+
return "ogg";
|
|
242
|
+
}
|
|
243
|
+
// MP3: ID3 header
|
|
244
|
+
if (buffer[0] === 0x49 && buffer[1] === 0x44 && buffer[2] === 0x33) {
|
|
245
|
+
return "mp3";
|
|
246
|
+
}
|
|
247
|
+
// MP3: MPEG sync word (0xFF 0xE0–0xFF)
|
|
248
|
+
if (buffer[0] === 0xff && (buffer[1] & 0xe0) === 0xe0) {
|
|
249
|
+
return "mpeg";
|
|
250
|
+
}
|
|
251
|
+
// M4A / AAC: "ftyp" box at offset 4
|
|
252
|
+
if (buffer.length >= 8 &&
|
|
253
|
+
buffer[4] === 0x66 &&
|
|
254
|
+
buffer[5] === 0x74 &&
|
|
255
|
+
buffer[6] === 0x79 &&
|
|
256
|
+
buffer[7] === 0x70) {
|
|
257
|
+
return "mp4";
|
|
258
|
+
}
|
|
259
|
+
return "mp3";
|
|
260
|
+
}
|
|
261
|
+
}
|
package/dist/neurolink.d.ts
CHANGED
|
@@ -40,7 +40,26 @@ export declare const STREAM_DEDUP_CONTEXT_KEY: "_streamDedupContext";
|
|
|
40
40
|
export declare function markStreamProviderEmittedGenerationEnd(options: {
|
|
41
41
|
_streamDedupContext?: StreamGenerationEndContext;
|
|
42
42
|
} | undefined): void;
|
|
43
|
+
/**
|
|
44
|
+
* Symbol-based brand for cross-module identification without circular imports.
|
|
45
|
+
*
|
|
46
|
+
* Provider constructors receive `sdk?: unknown` (the factory layer's
|
|
47
|
+
* contract). Rather than duck-typing via `"getInMemoryServers" in sdk`,
|
|
48
|
+
* use `isNeuroLink(value)` from this module to do a brand check —
|
|
49
|
+
* survives minification AND doesn't rely on method-name stability.
|
|
50
|
+
*/
|
|
51
|
+
export declare const NEUROLINK_BRAND: unique symbol;
|
|
52
|
+
/**
|
|
53
|
+
* Type-guard for opaque values that should be a {@link NeuroLink} instance.
|
|
54
|
+
*
|
|
55
|
+
* Designed for the provider-factory boundary where TS can't carry the type
|
|
56
|
+
* through `UnknownRecord` without forcing every caller into a circular
|
|
57
|
+
* dependency. Cheap to call and unaffected by minification.
|
|
58
|
+
*/
|
|
59
|
+
export declare function isNeuroLink(value: unknown): value is NeuroLink;
|
|
43
60
|
export declare class NeuroLink {
|
|
61
|
+
/** @internal Brand for cross-module identification — see {@link isNeuroLink}. */
|
|
62
|
+
readonly [NEUROLINK_BRAND]: true;
|
|
44
63
|
private mcpInitialized;
|
|
45
64
|
private mcpSkipped;
|
|
46
65
|
private mcpInitPromise;
|
|
@@ -570,6 +589,7 @@ export declare class NeuroLink {
|
|
|
570
589
|
* @since 1.0.0
|
|
571
590
|
*/
|
|
572
591
|
generate(optionsOrPrompt: GenerateOptions | DynamicOptions | string): Promise<GenerateResult>;
|
|
592
|
+
private fireConsumerOnErrorIfNotFired;
|
|
573
593
|
/**
|
|
574
594
|
* Curator P2-3: wraps a generate/stream call with the fallback
|
|
575
595
|
* orchestration (`providerFallback` callback + `modelChain` walker).
|
|
@@ -603,6 +623,16 @@ export declare class NeuroLink {
|
|
|
603
623
|
* Handle PPT generation mode
|
|
604
624
|
*/
|
|
605
625
|
private generateWithPPT;
|
|
626
|
+
/**
|
|
627
|
+
* Dispatch a music-generation request to the registered music handler
|
|
628
|
+
* for the provider named in `options.output.music.provider`.
|
|
629
|
+
*/
|
|
630
|
+
private generateWithMusic;
|
|
631
|
+
/**
|
|
632
|
+
* Dispatch an avatar (lip-sync) request to the registered avatar handler
|
|
633
|
+
* for the provider named in `options.output.avatar.provider`.
|
|
634
|
+
*/
|
|
635
|
+
private generateWithAvatar;
|
|
606
636
|
/**
|
|
607
637
|
* Generate with workflow engine integration
|
|
608
638
|
* Returns both original and processed responses for AB testing
|