@sahan-sac/ai-core 0.3.0 → 0.3.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.js +15 -609
- package/dist/availability.js +9 -458
- package/dist/chunk-BL4J2JNX.js +48 -0
- package/dist/chunk-MRNQPHWI.js +194 -0
- package/dist/chunk-PMC3UWQ2.js +10 -0
- package/dist/chunk-R3YY2Y7S.js +571 -0
- package/dist/chunk-RBSLNDFW.js +61 -0
- package/dist/chunk-ZIHRZXPE.js +109 -0
- package/dist/env.js +6 -102
- package/dist/image.js +14 -236
- package/dist/index.js +5 -102
- package/dist/log.js +3 -6
- package/dist/models.js +9 -51
- package/dist/providers.js +20 -582
- package/dist/vertex.js +4 -43
- package/package.json +1 -1
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getVertexAccessToken
|
|
3
|
+
} from "./chunk-BL4J2JNX.js";
|
|
4
|
+
import {
|
|
5
|
+
imageModels,
|
|
6
|
+
paidAllowed,
|
|
7
|
+
vertexConfigured
|
|
8
|
+
} from "./chunk-RBSLNDFW.js";
|
|
9
|
+
|
|
10
|
+
// src/image.ts
|
|
11
|
+
import "server-only";
|
|
12
|
+
var DEFAULT_IMAGE_MODELS = [
|
|
13
|
+
{ model: "gemini-3.1-flash-image", location: "global" },
|
|
14
|
+
{ model: "gemini-2.5-flash-image", location: "us-central1" }
|
|
15
|
+
];
|
|
16
|
+
function defaultLocation(model) {
|
|
17
|
+
return /^gemini-3/.test(model) ? "global" : "us-central1";
|
|
18
|
+
}
|
|
19
|
+
function imageModelChain(config) {
|
|
20
|
+
const chain = config.model ? [{ model: config.model, location: config.location ?? defaultLocation(config.model) }] : [];
|
|
21
|
+
for (const candidate of DEFAULT_IMAGE_MODELS) {
|
|
22
|
+
if (!chain.some((entry) => entry.model === candidate.model)) chain.push(candidate);
|
|
23
|
+
}
|
|
24
|
+
return chain;
|
|
25
|
+
}
|
|
26
|
+
function endpoint(project, target, method) {
|
|
27
|
+
const host = target.location === "global" ? "aiplatform.googleapis.com" : `${target.location}-aiplatform.googleapis.com`;
|
|
28
|
+
return `https://${host}/v1/projects/${project}/locations/${target.location}/publishers/google/models/${target.model}:${method}`;
|
|
29
|
+
}
|
|
30
|
+
function requestFor(target, prompt, aspectRatio) {
|
|
31
|
+
if (target.model.startsWith("imagen-")) {
|
|
32
|
+
return {
|
|
33
|
+
method: "predict",
|
|
34
|
+
body: {
|
|
35
|
+
instances: [{ prompt }],
|
|
36
|
+
parameters: { sampleCount: 1, aspectRatio, safetySetting: "block_medium_and_above", personGeneration: "allow_adult" }
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
method: "generateContent",
|
|
42
|
+
body: {
|
|
43
|
+
contents: [{ role: "user", parts: [{ text: prompt }] }],
|
|
44
|
+
generationConfig: { responseModalities: ["IMAGE"], imageConfig: { aspectRatio } }
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function extractImage(data) {
|
|
49
|
+
const prediction = data?.predictions?.[0];
|
|
50
|
+
if (prediction?.bytesBase64Encoded) return { base64: prediction.bytesBase64Encoded, mimeType: prediction.mimeType || "image/png" };
|
|
51
|
+
const parts = data?.candidates?.[0]?.content?.parts;
|
|
52
|
+
const inline = parts?.find((part) => part.inlineData?.data)?.inlineData;
|
|
53
|
+
return inline?.data ? { base64: inline.data, mimeType: inline.mimeType || "image/png" } : null;
|
|
54
|
+
}
|
|
55
|
+
async function generateImageVertex(prompt, config, options = {}) {
|
|
56
|
+
const fetchImpl = options.fetchImpl ?? fetch;
|
|
57
|
+
const aspectRatio = options.aspectRatio ?? "16:9";
|
|
58
|
+
let accessToken;
|
|
59
|
+
try {
|
|
60
|
+
accessToken = await getVertexAccessToken(
|
|
61
|
+
{ clientEmail: config.clientEmail, privateKey: config.privateKey, tokenUri: config.tokenUri },
|
|
62
|
+
fetchImpl
|
|
63
|
+
);
|
|
64
|
+
} catch (error) {
|
|
65
|
+
return { ok: false, error: `Image generation failed: ${error instanceof Error ? error.message : "authentication error"}` };
|
|
66
|
+
}
|
|
67
|
+
const failures = [];
|
|
68
|
+
for (const target of imageModelChain(config)) {
|
|
69
|
+
if (options.signal?.aborted) return { ok: false, error: "Image generation timed out." };
|
|
70
|
+
const { method, body } = requestFor(target, prompt, aspectRatio);
|
|
71
|
+
try {
|
|
72
|
+
const response = await fetchImpl(endpoint(config.project, target, method), {
|
|
73
|
+
method: "POST",
|
|
74
|
+
headers: { "content-type": "application/json", authorization: `Bearer ${accessToken}` },
|
|
75
|
+
signal: options.signal,
|
|
76
|
+
body: JSON.stringify(body)
|
|
77
|
+
});
|
|
78
|
+
if (!response.ok) {
|
|
79
|
+
failures.push(`${target.model}: HTTP ${response.status}`);
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
const image = extractImage(await response.json());
|
|
83
|
+
if (image) return { ok: true, ...image };
|
|
84
|
+
failures.push(`${target.model}: no image data`);
|
|
85
|
+
} catch (error) {
|
|
86
|
+
if (options.signal?.aborted) return { ok: false, error: "Image generation timed out." };
|
|
87
|
+
failures.push(`${target.model}: ${error instanceof Error ? error.message : "transport error"}`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return { ok: false, error: `Image generation failed (${failures.join("; ")}).` };
|
|
91
|
+
}
|
|
92
|
+
function vertexImageAvailable(env) {
|
|
93
|
+
return vertexConfigured(env);
|
|
94
|
+
}
|
|
95
|
+
var FLUX_SIZE = {
|
|
96
|
+
"16:9": { width: 1344, height: 768 },
|
|
97
|
+
"4:3": { width: 1024, height: 768 },
|
|
98
|
+
"1:1": { width: 1024, height: 1024 }
|
|
99
|
+
};
|
|
100
|
+
function nvidiaImageRequest(model, prompt, aspectRatio, seed) {
|
|
101
|
+
const size = FLUX_SIZE[aspectRatio];
|
|
102
|
+
if (/schnell/.test(model)) return { prompt, ...size, steps: 4, seed };
|
|
103
|
+
return { prompt, ...size, steps: 30, cfg_scale: 3.5, mode: "base", seed };
|
|
104
|
+
}
|
|
105
|
+
function extractNvidiaImage(data) {
|
|
106
|
+
const artifact = data?.artifacts?.[0];
|
|
107
|
+
if (!artifact?.base64 || artifact.finishReason && artifact.finishReason !== "SUCCESS") return null;
|
|
108
|
+
const mimeType = artifact.base64.startsWith("/9j/") ? "image/jpeg" : artifact.base64.startsWith("UklG") ? "image/webp" : "image/png";
|
|
109
|
+
return { base64: artifact.base64, mimeType };
|
|
110
|
+
}
|
|
111
|
+
async function postForImage(model, url, init, extract, options) {
|
|
112
|
+
try {
|
|
113
|
+
const response = await (options.fetchImpl ?? fetch)(url, {
|
|
114
|
+
method: "POST",
|
|
115
|
+
headers: { "content-type": "application/json", ...init.headers },
|
|
116
|
+
signal: options.signal,
|
|
117
|
+
body: JSON.stringify(init.body)
|
|
118
|
+
});
|
|
119
|
+
if (!response.ok) return { ok: false, error: `${model}: HTTP ${response.status}` };
|
|
120
|
+
const image = extract(await response.json());
|
|
121
|
+
return image ? { ok: true, ...image } : { ok: false, error: `${model}: no image (filtered or empty)` };
|
|
122
|
+
} catch (error) {
|
|
123
|
+
if (options.signal?.aborted) return { ok: false, error: "Image generation timed out." };
|
|
124
|
+
return { ok: false, error: `${model}: ${error instanceof Error ? error.message : "transport error"}` };
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
function generateImageNvidia(prompt, config, aspectRatio, options) {
|
|
128
|
+
return postForImage(
|
|
129
|
+
config.model,
|
|
130
|
+
`https://ai.api.nvidia.com/v1/genai/${config.model}`,
|
|
131
|
+
{
|
|
132
|
+
headers: { authorization: `Bearer ${config.apiKey}`, accept: "application/json" },
|
|
133
|
+
body: nvidiaImageRequest(config.model, prompt, aspectRatio, Math.floor(Math.random() * 2 ** 31))
|
|
134
|
+
},
|
|
135
|
+
extractNvidiaImage,
|
|
136
|
+
options
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
function generateImageGemini(prompt, config, aspectRatio, options) {
|
|
140
|
+
return postForImage(
|
|
141
|
+
config.model,
|
|
142
|
+
`https://generativelanguage.googleapis.com/v1beta/models/${config.model}:generateContent`,
|
|
143
|
+
{
|
|
144
|
+
headers: { "x-goog-api-key": config.apiKey },
|
|
145
|
+
body: { contents: [{ role: "user", parts: [{ text: prompt }] }], generationConfig: { responseModalities: ["IMAGE"], imageConfig: { aspectRatio } } }
|
|
146
|
+
},
|
|
147
|
+
extractImage,
|
|
148
|
+
options
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
function imageConfigFromEnv(env) {
|
|
152
|
+
const models = imageModels(env);
|
|
153
|
+
const paid = paidAllowed(env);
|
|
154
|
+
const config = {};
|
|
155
|
+
if (env.NVIDIA_API_KEY) config.nvidia = { apiKey: env.NVIDIA_API_KEY, model: models.nvidia };
|
|
156
|
+
if (paid && env.GEMINI_API_KEY) config.gemini = { apiKey: env.GEMINI_API_KEY, model: models.gemini };
|
|
157
|
+
if (paid && vertexImageAvailable(env)) {
|
|
158
|
+
config.vertex = {
|
|
159
|
+
clientEmail: env.GOOGLE_CLIENT_EMAIL,
|
|
160
|
+
privateKey: env.GOOGLE_PRIVATE_KEY,
|
|
161
|
+
tokenUri: env.GOOGLE_TOKEN_URI,
|
|
162
|
+
project: env.GOOGLE_CLOUD_PROJECT,
|
|
163
|
+
model: models.vertex
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
return config.nvidia || config.gemini || config.vertex ? config : null;
|
|
167
|
+
}
|
|
168
|
+
async function generateImage(prompt, config, options = {}) {
|
|
169
|
+
const aspectRatio = options.aspectRatio ?? "16:9";
|
|
170
|
+
const attempts = [];
|
|
171
|
+
if (config.nvidia) attempts.push(() => generateImageNvidia(prompt, config.nvidia, aspectRatio, options));
|
|
172
|
+
if (config.gemini) attempts.push(() => generateImageGemini(prompt, config.gemini, aspectRatio, options));
|
|
173
|
+
if (config.vertex) attempts.push(() => generateImageVertex(prompt, config.vertex, options));
|
|
174
|
+
const failures = [];
|
|
175
|
+
for (const run of attempts) {
|
|
176
|
+
if (options.signal?.aborted) return { ok: false, error: "Image generation timed out." };
|
|
177
|
+
const outcome = await run();
|
|
178
|
+
if (outcome.ok) return outcome;
|
|
179
|
+
failures.push(outcome.error);
|
|
180
|
+
}
|
|
181
|
+
return { ok: false, error: failures.length ? `Image generation failed (${failures.join("; ")}).` : "No image provider is configured." };
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export {
|
|
185
|
+
DEFAULT_IMAGE_MODELS,
|
|
186
|
+
imageModelChain,
|
|
187
|
+
extractImage,
|
|
188
|
+
generateImageVertex,
|
|
189
|
+
vertexImageAvailable,
|
|
190
|
+
nvidiaImageRequest,
|
|
191
|
+
extractNvidiaImage,
|
|
192
|
+
imageConfigFromEnv,
|
|
193
|
+
generateImage
|
|
194
|
+
};
|