@wopr-network/platform-core 1.10.0 → 1.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/dist/monetization/adapters/bootstrap.d.ts +11 -3
- package/dist/monetization/adapters/bootstrap.js +15 -3
- package/dist/monetization/adapters/bootstrap.test.js +19 -6
- package/package.json +1 -1
- package/src/monetization/adapters/bootstrap.test.ts +19 -6
- package/src/monetization/adapters/bootstrap.ts +22 -3
|
@@ -12,11 +12,10 @@
|
|
|
12
12
|
* - tts (Chatterbox GPU, ElevenLabs)
|
|
13
13
|
* - transcription (Deepgram)
|
|
14
14
|
* - embeddings (OpenRouter)
|
|
15
|
-
*
|
|
16
|
-
* Image-generation (Nano Banana, Replicate) will be wired once the
|
|
17
|
-
* image-gen-factory PR merges.
|
|
15
|
+
* - image-generation (Replicate, Nano Banana)
|
|
18
16
|
*/
|
|
19
17
|
import { type EmbeddingsFactoryConfig } from "./embeddings-factory.js";
|
|
18
|
+
import { type ImageGenFactoryConfig } from "./image-gen-factory.js";
|
|
20
19
|
import { type TextGenFactoryConfig } from "./text-gen-factory.js";
|
|
21
20
|
import { type TranscriptionFactoryConfig } from "./transcription-factory.js";
|
|
22
21
|
import { type TTSFactoryConfig } from "./tts-factory.js";
|
|
@@ -31,6 +30,8 @@ export interface BootstrapConfig {
|
|
|
31
30
|
transcription?: TranscriptionFactoryConfig;
|
|
32
31
|
/** Embeddings adapter config */
|
|
33
32
|
embeddings?: EmbeddingsFactoryConfig;
|
|
33
|
+
/** Image generation adapter config */
|
|
34
|
+
imageGen?: ImageGenFactoryConfig;
|
|
34
35
|
}
|
|
35
36
|
/** Result of bootstrapping all adapters. */
|
|
36
37
|
export interface BootstrapResult {
|
|
@@ -42,6 +43,12 @@ export interface BootstrapResult {
|
|
|
42
43
|
* capabilities (e.g. OpenRouter for both text-gen and embeddings). Each
|
|
43
44
|
* instance is independently configured. Use the per-capability factory
|
|
44
45
|
* results if you need a name→adapter map within a single capability.
|
|
46
|
+
*
|
|
47
|
+
* NOTE: Some adapters advertise more capabilities than the factory that
|
|
48
|
+
* created them (e.g. Replicate advertises text-generation and transcription
|
|
49
|
+
* in addition to image-generation). The ArbitrageRouter should use the
|
|
50
|
+
* factory-assigned capability (reflected in byCapability), not the adapter's
|
|
51
|
+
* own capabilities array, for routing decisions.
|
|
45
52
|
*/
|
|
46
53
|
adapters: ProviderAdapter[];
|
|
47
54
|
/** Names of providers that were skipped (missing config), grouped by capability. */
|
|
@@ -68,6 +75,7 @@ export declare function bootstrapAdapters(config: BootstrapConfig): BootstrapRes
|
|
|
68
75
|
* - CHATTERBOX_BASE_URL, ELEVENLABS_API_KEY (TTS)
|
|
69
76
|
* - DEEPGRAM_API_KEY (transcription)
|
|
70
77
|
* - OPENROUTER_API_KEY (embeddings)
|
|
78
|
+
* - REPLICATE_API_TOKEN, NANO_BANANA_API_KEY (image-gen)
|
|
71
79
|
*
|
|
72
80
|
* Accepts optional per-capability config overrides.
|
|
73
81
|
*/
|
|
@@ -12,11 +12,10 @@
|
|
|
12
12
|
* - tts (Chatterbox GPU, ElevenLabs)
|
|
13
13
|
* - transcription (Deepgram)
|
|
14
14
|
* - embeddings (OpenRouter)
|
|
15
|
-
*
|
|
16
|
-
* Image-generation (Nano Banana, Replicate) will be wired once the
|
|
17
|
-
* image-gen-factory PR merges.
|
|
15
|
+
* - image-generation (Replicate, Nano Banana)
|
|
18
16
|
*/
|
|
19
17
|
import { createEmbeddingsAdapters } from "./embeddings-factory.js";
|
|
18
|
+
import { createImageGenAdapters } from "./image-gen-factory.js";
|
|
20
19
|
import { createTextGenAdapters } from "./text-gen-factory.js";
|
|
21
20
|
import { createTranscriptionAdapters } from "./transcription-factory.js";
|
|
22
21
|
import { createTTSAdapters } from "./tts-factory.js";
|
|
@@ -31,11 +30,13 @@ export function bootstrapAdapters(config) {
|
|
|
31
30
|
const tts = createTTSAdapters(config.tts ?? {});
|
|
32
31
|
const transcription = createTranscriptionAdapters(config.transcription ?? {});
|
|
33
32
|
const embeddings = createEmbeddingsAdapters(config.embeddings ?? {});
|
|
33
|
+
const imageGen = createImageGenAdapters(config.imageGen ?? {});
|
|
34
34
|
const adapters = [
|
|
35
35
|
...textGen.adapters,
|
|
36
36
|
...tts.adapters,
|
|
37
37
|
...transcription.adapters,
|
|
38
38
|
...embeddings.adapters,
|
|
39
|
+
...imageGen.adapters,
|
|
39
40
|
];
|
|
40
41
|
const skipped = {};
|
|
41
42
|
if (textGen.skipped.length > 0)
|
|
@@ -46,6 +47,8 @@ export function bootstrapAdapters(config) {
|
|
|
46
47
|
skipped.transcription = transcription.skipped;
|
|
47
48
|
if (embeddings.skipped.length > 0)
|
|
48
49
|
skipped.embeddings = embeddings.skipped;
|
|
50
|
+
if (imageGen.skipped.length > 0)
|
|
51
|
+
skipped["image-generation"] = imageGen.skipped;
|
|
49
52
|
let totalSkipped = 0;
|
|
50
53
|
for (const list of Object.values(skipped)) {
|
|
51
54
|
totalSkipped += list.length;
|
|
@@ -61,6 +64,7 @@ export function bootstrapAdapters(config) {
|
|
|
61
64
|
tts: tts.adapters.length,
|
|
62
65
|
transcription: transcription.adapters.length,
|
|
63
66
|
embeddings: embeddings.adapters.length,
|
|
67
|
+
"image-generation": imageGen.adapters.length,
|
|
64
68
|
},
|
|
65
69
|
},
|
|
66
70
|
};
|
|
@@ -73,6 +77,7 @@ export function bootstrapAdapters(config) {
|
|
|
73
77
|
* - CHATTERBOX_BASE_URL, ELEVENLABS_API_KEY (TTS)
|
|
74
78
|
* - DEEPGRAM_API_KEY (transcription)
|
|
75
79
|
* - OPENROUTER_API_KEY (embeddings)
|
|
80
|
+
* - REPLICATE_API_TOKEN, NANO_BANANA_API_KEY (image-gen)
|
|
76
81
|
*
|
|
77
82
|
* Accepts optional per-capability config overrides.
|
|
78
83
|
*/
|
|
@@ -99,5 +104,12 @@ export function bootstrapAdaptersFromEnv(overrides) {
|
|
|
99
104
|
openrouterApiKey: process.env.OPENROUTER_API_KEY,
|
|
100
105
|
...overrides?.embeddings,
|
|
101
106
|
},
|
|
107
|
+
imageGen: {
|
|
108
|
+
replicateApiToken: process.env.REPLICATE_API_TOKEN,
|
|
109
|
+
// Separate env var from GEMINI_API_KEY (used for text-gen) to avoid
|
|
110
|
+
// silently enabling image-gen when only text-gen is intended.
|
|
111
|
+
geminiApiKey: process.env.NANO_BANANA_API_KEY,
|
|
112
|
+
...overrides?.imageGen,
|
|
113
|
+
},
|
|
102
114
|
});
|
|
103
115
|
}
|
|
@@ -20,10 +20,14 @@ describe("bootstrapAdapters", () => {
|
|
|
20
20
|
embeddings: {
|
|
21
21
|
openrouterApiKey: "sk-or",
|
|
22
22
|
},
|
|
23
|
+
imageGen: {
|
|
24
|
+
replicateApiToken: "r8-rep",
|
|
25
|
+
geminiApiKey: "sk-gem",
|
|
26
|
+
},
|
|
23
27
|
});
|
|
24
|
-
// 5 text-gen + 2 TTS + 1 transcription + 1 embeddings =
|
|
25
|
-
expect(result.adapters).toHaveLength(
|
|
26
|
-
expect(result.summary.total).toBe(
|
|
28
|
+
// 5 text-gen + 2 TTS + 1 transcription + 1 embeddings + 2 image-gen = 11
|
|
29
|
+
expect(result.adapters).toHaveLength(11);
|
|
30
|
+
expect(result.summary.total).toBe(11);
|
|
27
31
|
expect(result.summary.skipped).toBe(0);
|
|
28
32
|
});
|
|
29
33
|
it("allows duplicate provider names across capabilities", () => {
|
|
@@ -48,6 +52,7 @@ describe("bootstrapAdapters", () => {
|
|
|
48
52
|
tts: 1,
|
|
49
53
|
transcription: 1,
|
|
50
54
|
embeddings: 1,
|
|
55
|
+
"image-generation": 0,
|
|
51
56
|
});
|
|
52
57
|
});
|
|
53
58
|
it("tracks skipped providers by capability", () => {
|
|
@@ -61,6 +66,7 @@ describe("bootstrapAdapters", () => {
|
|
|
61
66
|
expect(result.skipped.transcription).toEqual(["deepgram"]);
|
|
62
67
|
expect(result.skipped.embeddings).toEqual(["openrouter"]);
|
|
63
68
|
expect(result.skipped["text-generation"]).toEqual(["gemini", "minimax", "kimi", "openrouter"]);
|
|
69
|
+
expect(result.skipped["image-generation"]).toEqual(["replicate", "nano-banana"]);
|
|
64
70
|
});
|
|
65
71
|
it("returns empty result when no config provided", () => {
|
|
66
72
|
const result = bootstrapAdapters({});
|
|
@@ -82,6 +88,7 @@ describe("bootstrapAdapters", () => {
|
|
|
82
88
|
expect(result.summary.byCapability.tts).toBe(0);
|
|
83
89
|
expect(result.summary.byCapability.transcription).toBe(0);
|
|
84
90
|
expect(result.summary.byCapability.embeddings).toBe(0);
|
|
91
|
+
expect(result.summary.byCapability["image-generation"]).toBe(0);
|
|
85
92
|
});
|
|
86
93
|
it("passes per-adapter overrides through", () => {
|
|
87
94
|
const result = bootstrapAdapters({
|
|
@@ -110,10 +117,12 @@ describe("bootstrapAdaptersFromEnv", () => {
|
|
|
110
117
|
vi.stubEnv("CHATTERBOX_BASE_URL", "http://chatterbox:8000");
|
|
111
118
|
vi.stubEnv("ELEVENLABS_API_KEY", "env-el");
|
|
112
119
|
vi.stubEnv("DEEPGRAM_API_KEY", "env-dg");
|
|
120
|
+
vi.stubEnv("REPLICATE_API_TOKEN", "r8-rep");
|
|
121
|
+
vi.stubEnv("NANO_BANANA_API_KEY", "env-nb");
|
|
113
122
|
const result = bootstrapAdaptersFromEnv();
|
|
114
|
-
// 5 text-gen + 2 TTS + 1 transcription + 1 embeddings =
|
|
115
|
-
expect(result.adapters).toHaveLength(
|
|
116
|
-
expect(result.summary.total).toBe(
|
|
123
|
+
// 5 text-gen + 2 TTS + 1 transcription + 1 embeddings + 2 image-gen = 11
|
|
124
|
+
expect(result.adapters).toHaveLength(11);
|
|
125
|
+
expect(result.summary.total).toBe(11);
|
|
117
126
|
});
|
|
118
127
|
it("returns empty when no env vars set", () => {
|
|
119
128
|
vi.stubEnv("DEEPSEEK_API_KEY", "");
|
|
@@ -124,6 +133,8 @@ describe("bootstrapAdaptersFromEnv", () => {
|
|
|
124
133
|
vi.stubEnv("CHATTERBOX_BASE_URL", "");
|
|
125
134
|
vi.stubEnv("ELEVENLABS_API_KEY", "");
|
|
126
135
|
vi.stubEnv("DEEPGRAM_API_KEY", "");
|
|
136
|
+
vi.stubEnv("REPLICATE_API_TOKEN", "");
|
|
137
|
+
vi.stubEnv("NANO_BANANA_API_KEY", "");
|
|
127
138
|
const result = bootstrapAdaptersFromEnv();
|
|
128
139
|
expect(result.adapters).toHaveLength(0);
|
|
129
140
|
expect(result.summary.skipped).toBeGreaterThan(0);
|
|
@@ -137,6 +148,8 @@ describe("bootstrapAdaptersFromEnv", () => {
|
|
|
137
148
|
vi.stubEnv("CHATTERBOX_BASE_URL", "");
|
|
138
149
|
vi.stubEnv("ELEVENLABS_API_KEY", "");
|
|
139
150
|
vi.stubEnv("DEEPGRAM_API_KEY", "");
|
|
151
|
+
vi.stubEnv("REPLICATE_API_TOKEN", "");
|
|
152
|
+
vi.stubEnv("NANO_BANANA_API_KEY", "");
|
|
140
153
|
const result = bootstrapAdaptersFromEnv({
|
|
141
154
|
textGen: { deepseek: { marginMultiplier: 2.0 } },
|
|
142
155
|
});
|
package/package.json
CHANGED
|
@@ -21,11 +21,15 @@ describe("bootstrapAdapters", () => {
|
|
|
21
21
|
embeddings: {
|
|
22
22
|
openrouterApiKey: "sk-or",
|
|
23
23
|
},
|
|
24
|
+
imageGen: {
|
|
25
|
+
replicateApiToken: "r8-rep",
|
|
26
|
+
geminiApiKey: "sk-gem",
|
|
27
|
+
},
|
|
24
28
|
});
|
|
25
29
|
|
|
26
|
-
// 5 text-gen + 2 TTS + 1 transcription + 1 embeddings =
|
|
27
|
-
expect(result.adapters).toHaveLength(
|
|
28
|
-
expect(result.summary.total).toBe(
|
|
30
|
+
// 5 text-gen + 2 TTS + 1 transcription + 1 embeddings + 2 image-gen = 11
|
|
31
|
+
expect(result.adapters).toHaveLength(11);
|
|
32
|
+
expect(result.summary.total).toBe(11);
|
|
29
33
|
expect(result.summary.skipped).toBe(0);
|
|
30
34
|
});
|
|
31
35
|
|
|
@@ -54,6 +58,7 @@ describe("bootstrapAdapters", () => {
|
|
|
54
58
|
tts: 1,
|
|
55
59
|
transcription: 1,
|
|
56
60
|
embeddings: 1,
|
|
61
|
+
"image-generation": 0,
|
|
57
62
|
});
|
|
58
63
|
});
|
|
59
64
|
|
|
@@ -69,6 +74,7 @@ describe("bootstrapAdapters", () => {
|
|
|
69
74
|
expect(result.skipped.transcription).toEqual(["deepgram"]);
|
|
70
75
|
expect(result.skipped.embeddings).toEqual(["openrouter"]);
|
|
71
76
|
expect(result.skipped["text-generation"]).toEqual(["gemini", "minimax", "kimi", "openrouter"]);
|
|
77
|
+
expect(result.skipped["image-generation"]).toEqual(["replicate", "nano-banana"]);
|
|
72
78
|
});
|
|
73
79
|
|
|
74
80
|
it("returns empty result when no config provided", () => {
|
|
@@ -96,6 +102,7 @@ describe("bootstrapAdapters", () => {
|
|
|
96
102
|
expect(result.summary.byCapability.tts).toBe(0);
|
|
97
103
|
expect(result.summary.byCapability.transcription).toBe(0);
|
|
98
104
|
expect(result.summary.byCapability.embeddings).toBe(0);
|
|
105
|
+
expect(result.summary.byCapability["image-generation"]).toBe(0);
|
|
99
106
|
});
|
|
100
107
|
|
|
101
108
|
it("passes per-adapter overrides through", () => {
|
|
@@ -129,12 +136,14 @@ describe("bootstrapAdaptersFromEnv", () => {
|
|
|
129
136
|
vi.stubEnv("CHATTERBOX_BASE_URL", "http://chatterbox:8000");
|
|
130
137
|
vi.stubEnv("ELEVENLABS_API_KEY", "env-el");
|
|
131
138
|
vi.stubEnv("DEEPGRAM_API_KEY", "env-dg");
|
|
139
|
+
vi.stubEnv("REPLICATE_API_TOKEN", "r8-rep");
|
|
140
|
+
vi.stubEnv("NANO_BANANA_API_KEY", "env-nb");
|
|
132
141
|
|
|
133
142
|
const result = bootstrapAdaptersFromEnv();
|
|
134
143
|
|
|
135
|
-
// 5 text-gen + 2 TTS + 1 transcription + 1 embeddings =
|
|
136
|
-
expect(result.adapters).toHaveLength(
|
|
137
|
-
expect(result.summary.total).toBe(
|
|
144
|
+
// 5 text-gen + 2 TTS + 1 transcription + 1 embeddings + 2 image-gen = 11
|
|
145
|
+
expect(result.adapters).toHaveLength(11);
|
|
146
|
+
expect(result.summary.total).toBe(11);
|
|
138
147
|
});
|
|
139
148
|
|
|
140
149
|
it("returns empty when no env vars set", () => {
|
|
@@ -146,6 +155,8 @@ describe("bootstrapAdaptersFromEnv", () => {
|
|
|
146
155
|
vi.stubEnv("CHATTERBOX_BASE_URL", "");
|
|
147
156
|
vi.stubEnv("ELEVENLABS_API_KEY", "");
|
|
148
157
|
vi.stubEnv("DEEPGRAM_API_KEY", "");
|
|
158
|
+
vi.stubEnv("REPLICATE_API_TOKEN", "");
|
|
159
|
+
vi.stubEnv("NANO_BANANA_API_KEY", "");
|
|
149
160
|
|
|
150
161
|
const result = bootstrapAdaptersFromEnv();
|
|
151
162
|
|
|
@@ -162,6 +173,8 @@ describe("bootstrapAdaptersFromEnv", () => {
|
|
|
162
173
|
vi.stubEnv("CHATTERBOX_BASE_URL", "");
|
|
163
174
|
vi.stubEnv("ELEVENLABS_API_KEY", "");
|
|
164
175
|
vi.stubEnv("DEEPGRAM_API_KEY", "");
|
|
176
|
+
vi.stubEnv("REPLICATE_API_TOKEN", "");
|
|
177
|
+
vi.stubEnv("NANO_BANANA_API_KEY", "");
|
|
165
178
|
|
|
166
179
|
const result = bootstrapAdaptersFromEnv({
|
|
167
180
|
textGen: { deepseek: { marginMultiplier: 2.0 } },
|
|
@@ -12,12 +12,11 @@
|
|
|
12
12
|
* - tts (Chatterbox GPU, ElevenLabs)
|
|
13
13
|
* - transcription (Deepgram)
|
|
14
14
|
* - embeddings (OpenRouter)
|
|
15
|
-
*
|
|
16
|
-
* Image-generation (Nano Banana, Replicate) will be wired once the
|
|
17
|
-
* image-gen-factory PR merges.
|
|
15
|
+
* - image-generation (Replicate, Nano Banana)
|
|
18
16
|
*/
|
|
19
17
|
|
|
20
18
|
import { createEmbeddingsAdapters, type EmbeddingsFactoryConfig } from "./embeddings-factory.js";
|
|
19
|
+
import { createImageGenAdapters, type ImageGenFactoryConfig } from "./image-gen-factory.js";
|
|
21
20
|
import { createTextGenAdapters, type TextGenFactoryConfig } from "./text-gen-factory.js";
|
|
22
21
|
import { createTranscriptionAdapters, type TranscriptionFactoryConfig } from "./transcription-factory.js";
|
|
23
22
|
import { createTTSAdapters, type TTSFactoryConfig } from "./tts-factory.js";
|
|
@@ -33,6 +32,8 @@ export interface BootstrapConfig {
|
|
|
33
32
|
transcription?: TranscriptionFactoryConfig;
|
|
34
33
|
/** Embeddings adapter config */
|
|
35
34
|
embeddings?: EmbeddingsFactoryConfig;
|
|
35
|
+
/** Image generation adapter config */
|
|
36
|
+
imageGen?: ImageGenFactoryConfig;
|
|
36
37
|
}
|
|
37
38
|
|
|
38
39
|
/** Result of bootstrapping all adapters. */
|
|
@@ -45,6 +46,12 @@ export interface BootstrapResult {
|
|
|
45
46
|
* capabilities (e.g. OpenRouter for both text-gen and embeddings). Each
|
|
46
47
|
* instance is independently configured. Use the per-capability factory
|
|
47
48
|
* results if you need a name→adapter map within a single capability.
|
|
49
|
+
*
|
|
50
|
+
* NOTE: Some adapters advertise more capabilities than the factory that
|
|
51
|
+
* created them (e.g. Replicate advertises text-generation and transcription
|
|
52
|
+
* in addition to image-generation). The ArbitrageRouter should use the
|
|
53
|
+
* factory-assigned capability (reflected in byCapability), not the adapter's
|
|
54
|
+
* own capabilities array, for routing decisions.
|
|
48
55
|
*/
|
|
49
56
|
adapters: ProviderAdapter[];
|
|
50
57
|
/** Names of providers that were skipped (missing config), grouped by capability. */
|
|
@@ -68,12 +75,14 @@ export function bootstrapAdapters(config: BootstrapConfig): BootstrapResult {
|
|
|
68
75
|
const tts = createTTSAdapters(config.tts ?? {});
|
|
69
76
|
const transcription = createTranscriptionAdapters(config.transcription ?? {});
|
|
70
77
|
const embeddings = createEmbeddingsAdapters(config.embeddings ?? {});
|
|
78
|
+
const imageGen = createImageGenAdapters(config.imageGen ?? {});
|
|
71
79
|
|
|
72
80
|
const adapters: ProviderAdapter[] = [
|
|
73
81
|
...textGen.adapters,
|
|
74
82
|
...tts.adapters,
|
|
75
83
|
...transcription.adapters,
|
|
76
84
|
...embeddings.adapters,
|
|
85
|
+
...imageGen.adapters,
|
|
77
86
|
];
|
|
78
87
|
|
|
79
88
|
const skipped: Record<string, string[]> = {};
|
|
@@ -81,6 +90,7 @@ export function bootstrapAdapters(config: BootstrapConfig): BootstrapResult {
|
|
|
81
90
|
if (tts.skipped.length > 0) skipped.tts = tts.skipped;
|
|
82
91
|
if (transcription.skipped.length > 0) skipped.transcription = transcription.skipped;
|
|
83
92
|
if (embeddings.skipped.length > 0) skipped.embeddings = embeddings.skipped;
|
|
93
|
+
if (imageGen.skipped.length > 0) skipped["image-generation"] = imageGen.skipped;
|
|
84
94
|
|
|
85
95
|
let totalSkipped = 0;
|
|
86
96
|
for (const list of Object.values(skipped)) {
|
|
@@ -98,6 +108,7 @@ export function bootstrapAdapters(config: BootstrapConfig): BootstrapResult {
|
|
|
98
108
|
tts: tts.adapters.length,
|
|
99
109
|
transcription: transcription.adapters.length,
|
|
100
110
|
embeddings: embeddings.adapters.length,
|
|
111
|
+
"image-generation": imageGen.adapters.length,
|
|
101
112
|
},
|
|
102
113
|
},
|
|
103
114
|
};
|
|
@@ -111,6 +122,7 @@ export function bootstrapAdapters(config: BootstrapConfig): BootstrapResult {
|
|
|
111
122
|
* - CHATTERBOX_BASE_URL, ELEVENLABS_API_KEY (TTS)
|
|
112
123
|
* - DEEPGRAM_API_KEY (transcription)
|
|
113
124
|
* - OPENROUTER_API_KEY (embeddings)
|
|
125
|
+
* - REPLICATE_API_TOKEN, NANO_BANANA_API_KEY (image-gen)
|
|
114
126
|
*
|
|
115
127
|
* Accepts optional per-capability config overrides.
|
|
116
128
|
*/
|
|
@@ -137,5 +149,12 @@ export function bootstrapAdaptersFromEnv(overrides?: Partial<BootstrapConfig>):
|
|
|
137
149
|
openrouterApiKey: process.env.OPENROUTER_API_KEY,
|
|
138
150
|
...overrides?.embeddings,
|
|
139
151
|
},
|
|
152
|
+
imageGen: {
|
|
153
|
+
replicateApiToken: process.env.REPLICATE_API_TOKEN,
|
|
154
|
+
// Separate env var from GEMINI_API_KEY (used for text-gen) to avoid
|
|
155
|
+
// silently enabling image-gen when only text-gen is intended.
|
|
156
|
+
geminiApiKey: process.env.NANO_BANANA_API_KEY,
|
|
157
|
+
...overrides?.imageGen,
|
|
158
|
+
},
|
|
140
159
|
});
|
|
141
160
|
}
|