@evolinkai/mcp 0.0.0-stage → 1.3.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/LICENSE +178 -0
- package/README.md +67 -2
- package/dist/core/src/config.d.ts +19 -0
- package/dist/core/src/config.d.ts.map +1 -0
- package/dist/core/src/config.js +88 -0
- package/dist/core/src/config.js.map +1 -0
- package/dist/core/src/data/model-params.d.ts +49 -0
- package/dist/core/src/data/model-params.d.ts.map +1 -0
- package/dist/core/src/data/model-params.generated.d.ts +2 -0
- package/dist/core/src/data/model-params.generated.d.ts.map +1 -0
- package/dist/core/src/data/model-params.generated.js +3 -0
- package/dist/core/src/data/model-params.generated.js.map +1 -0
- package/dist/core/src/data/model-params.js +22 -0
- package/dist/core/src/data/model-params.js.map +1 -0
- package/dist/core/src/request-context.d.ts +60 -0
- package/dist/core/src/request-context.d.ts.map +1 -0
- package/dist/core/src/request-context.js +39 -0
- package/dist/core/src/request-context.js.map +1 -0
- package/dist/core/src/server.d.ts +18 -0
- package/dist/core/src/server.d.ts.map +1 -0
- package/dist/core/src/server.js +84 -0
- package/dist/core/src/server.js.map +1 -0
- package/dist/core/src/services/api-client.d.ts +129 -0
- package/dist/core/src/services/api-client.d.ts.map +1 -0
- package/dist/core/src/services/api-client.js +163 -0
- package/dist/core/src/services/api-client.js.map +1 -0
- package/dist/core/src/services/error-handler.d.ts +51 -0
- package/dist/core/src/services/error-handler.d.ts.map +1 -0
- package/dist/core/src/services/error-handler.js +390 -0
- package/dist/core/src/services/error-handler.js.map +1 -0
- package/dist/core/src/services/file-client.d.ts +24 -0
- package/dist/core/src/services/file-client.d.ts.map +1 -0
- package/dist/core/src/services/file-client.js +100 -0
- package/dist/core/src/services/file-client.js.map +1 -0
- package/dist/core/src/services/http-policy.d.ts +40 -0
- package/dist/core/src/services/http-policy.d.ts.map +1 -0
- package/dist/core/src/services/http-policy.js +120 -0
- package/dist/core/src/services/http-policy.js.map +1 -0
- package/dist/core/src/services/model-catalog.d.ts +24 -0
- package/dist/core/src/services/model-catalog.d.ts.map +1 -0
- package/dist/core/src/services/model-catalog.js +45 -0
- package/dist/core/src/services/model-catalog.js.map +1 -0
- package/dist/core/src/services/param-validator.d.ts +21 -0
- package/dist/core/src/services/param-validator.d.ts.map +1 -0
- package/dist/core/src/services/param-validator.js +164 -0
- package/dist/core/src/services/param-validator.js.map +1 -0
- package/dist/core/src/services/pricing-client.d.ts +77 -0
- package/dist/core/src/services/pricing-client.d.ts.map +1 -0
- package/dist/core/src/services/pricing-client.js +332 -0
- package/dist/core/src/services/pricing-client.js.map +1 -0
- package/dist/core/src/services/upload-policy.d.ts +17 -0
- package/dist/core/src/services/upload-policy.d.ts.map +1 -0
- package/dist/core/src/services/upload-policy.js +160 -0
- package/dist/core/src/services/upload-policy.js.map +1 -0
- package/dist/core/src/tools/check-balance.d.ts +4 -0
- package/dist/core/src/tools/check-balance.d.ts.map +1 -0
- package/dist/core/src/tools/check-balance.js +78 -0
- package/dist/core/src/tools/check-balance.js.map +1 -0
- package/dist/core/src/tools/estimate-cost.d.ts +4 -0
- package/dist/core/src/tools/estimate-cost.d.ts.map +1 -0
- package/dist/core/src/tools/estimate-cost.js +127 -0
- package/dist/core/src/tools/estimate-cost.js.map +1 -0
- package/dist/core/src/tools/generate.d.ts +4 -0
- package/dist/core/src/tools/generate.d.ts.map +1 -0
- package/dist/core/src/tools/generate.js +178 -0
- package/dist/core/src/tools/generate.js.map +1 -0
- package/dist/core/src/tools/get-model.d.ts +5 -0
- package/dist/core/src/tools/get-model.d.ts.map +1 -0
- package/dist/core/src/tools/get-model.js +109 -0
- package/dist/core/src/tools/get-model.js.map +1 -0
- package/dist/core/src/tools/get-task.d.ts +7 -0
- package/dist/core/src/tools/get-task.d.ts.map +1 -0
- package/dist/core/src/tools/get-task.js +55 -0
- package/dist/core/src/tools/get-task.js.map +1 -0
- package/dist/core/src/tools/list-tasks.d.ts +6 -0
- package/dist/core/src/tools/list-tasks.d.ts.map +1 -0
- package/dist/core/src/tools/list-tasks.js +142 -0
- package/dist/core/src/tools/list-tasks.js.map +1 -0
- package/dist/core/src/tools/search-models.d.ts +5 -0
- package/dist/core/src/tools/search-models.d.ts.map +1 -0
- package/dist/core/src/tools/search-models.js +96 -0
- package/dist/core/src/tools/search-models.js.map +1 -0
- package/dist/core/src/tools/shared.d.ts +50 -0
- package/dist/core/src/tools/shared.d.ts.map +1 -0
- package/dist/core/src/tools/shared.js +129 -0
- package/dist/core/src/tools/shared.js.map +1 -0
- package/dist/core/src/tools/task-format.d.ts +32 -0
- package/dist/core/src/tools/task-format.d.ts.map +1 -0
- package/dist/core/src/tools/task-format.js +138 -0
- package/dist/core/src/tools/task-format.js.map +1 -0
- package/dist/core/src/tools/upload-file.d.ts +7 -0
- package/dist/core/src/tools/upload-file.d.ts.map +1 -0
- package/dist/core/src/tools/upload-file.js +104 -0
- package/dist/core/src/tools/upload-file.js.map +1 -0
- package/dist/core/src/version.d.ts +3 -0
- package/dist/core/src/version.d.ts.map +1 -0
- package/dist/core/src/version.js +3 -0
- package/dist/core/src/version.js.map +1 -0
- package/dist/evolink-media/src/index.d.ts +3 -0
- package/dist/evolink-media/src/index.d.ts.map +1 -0
- package/dist/evolink-media/src/index.js +16 -0
- package/dist/evolink-media/src/index.js.map +1 -0
- package/package.json +46 -4
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
import { isIP } from 'node:net';
|
|
2
|
+
import { CREDITS_PER_USD, formatUsd } from './error-handler.js';
|
|
3
|
+
import { DEFAULT_READ_TIMEOUT_MS, evoHeaders, fetchWithTimeout, readJsonBody, timeoutFromEnv, } from './http-policy.js';
|
|
4
|
+
const CACHE_TTL_MS = 5 * 60_000;
|
|
5
|
+
const MAX_STALE_MS = 24 * 60 * 60_000;
|
|
6
|
+
/** Gateway display rate: 1 USD = 6.8 CNY. */
|
|
7
|
+
const CNY_PER_USD = 6.8;
|
|
8
|
+
let cached;
|
|
9
|
+
let inflight;
|
|
10
|
+
/** Base for the public web API (pricing); EVOLINK_CONTROL_BASE points it at a staging host. */
|
|
11
|
+
export function controlBaseURL() {
|
|
12
|
+
const configured = (process.env.EVOLINK_CONTROL_BASE ?? 'https://api.evolink.ai').trim().replace(/\/$/, '');
|
|
13
|
+
let parsed;
|
|
14
|
+
try {
|
|
15
|
+
parsed = new URL(configured);
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
throw new Error('EVOLINK_CONTROL_BASE must be an absolute URL');
|
|
19
|
+
}
|
|
20
|
+
const loopback = parsed.hostname === 'localhost' || (isIP(parsed.hostname) !== 0 && parsed.hostname === '127.0.0.1');
|
|
21
|
+
if ((parsed.protocol !== 'https:' && !(parsed.protocol === 'http:' && loopback)) || parsed.username || parsed.password || parsed.search || parsed.hash) {
|
|
22
|
+
throw new Error('EVOLINK_CONTROL_BASE must use HTTPS, except for loopback development, and contain no credentials/query/fragment');
|
|
23
|
+
}
|
|
24
|
+
return configured;
|
|
25
|
+
}
|
|
26
|
+
const ROUTING_NOTE = /\$([\d,]*\.?\d+)(?:\s*[-–~]\s*\$?([\d,]*\.?\d+))?\s+per\s+([A-Za-z0-9 ]+?)(?=[.,;]|$)/;
|
|
27
|
+
/** Charges for optional inputs or features, as opposed to the generated output ("Reference to Video" is an output). */
|
|
28
|
+
const ADD_ON_NAME = /\binput (image|images|video|audio|text)\b|\breference (image|images|video seconds|audio)\b|web search|cached|cache (hit|write)|asset upload|输入/i;
|
|
29
|
+
function parseMetadata(value) {
|
|
30
|
+
if (!value)
|
|
31
|
+
return {};
|
|
32
|
+
try {
|
|
33
|
+
const parsed = JSON.parse(value);
|
|
34
|
+
return parsed && typeof parsed === 'object' ? parsed : {};
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return {};
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function unitFromRule(rule) {
|
|
41
|
+
switch (rule) {
|
|
42
|
+
case 'per_image': return 'image';
|
|
43
|
+
case 'per_second': return 'second';
|
|
44
|
+
case 'per_hour': return 'hour';
|
|
45
|
+
case 'per_1k':
|
|
46
|
+
case 'per_1k_tokens': return '1K tokens';
|
|
47
|
+
case 'per_token': return 'token';
|
|
48
|
+
default: return 'request';
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/** Unit and USD price of one SKU: the gateway's routing note first (it carries the corrected unit), the raw fields second. */
|
|
52
|
+
export function skuPrice(sku) {
|
|
53
|
+
const note = ROUTING_NOTE.exec(sku.routing_note ?? '');
|
|
54
|
+
let unit;
|
|
55
|
+
let minUsd;
|
|
56
|
+
let maxUsd;
|
|
57
|
+
if (note) {
|
|
58
|
+
unit = note[3].trim().toLowerCase();
|
|
59
|
+
minUsd = Number(note[1].replaceAll(',', ''));
|
|
60
|
+
maxUsd = note[2] ? Number(note[2].replaceAll(',', '')) : minUsd;
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
unit = unitFromRule(sku.billing_rule);
|
|
64
|
+
const range = sku.price_range;
|
|
65
|
+
if (range && typeof range.min_usd === 'number' && typeof range.max_usd === 'number') {
|
|
66
|
+
minUsd = range.min_usd;
|
|
67
|
+
maxUsd = range.max_usd;
|
|
68
|
+
}
|
|
69
|
+
else if (typeof sku.cny_price === 'number') {
|
|
70
|
+
minUsd = sku.cny_price / CNY_PER_USD;
|
|
71
|
+
maxUsd = minUsd;
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (!Number.isFinite(minUsd) || !Number.isFinite(maxUsd))
|
|
78
|
+
return undefined;
|
|
79
|
+
const metadata = parseMetadata(sku.metadata);
|
|
80
|
+
const tokenBased = /token/.test(unit);
|
|
81
|
+
const addOn = !tokenBased && (metadata.role === 'input_image' || ADD_ON_NAME.test(sku.sku_name));
|
|
82
|
+
const multipliers = sku.resolution_multipliers
|
|
83
|
+
?? (metadata.resolution_multipliers && typeof metadata.resolution_multipliers === 'object'
|
|
84
|
+
? metadata.resolution_multipliers
|
|
85
|
+
: undefined);
|
|
86
|
+
const price = {
|
|
87
|
+
sku_id: String(sku.sku_id),
|
|
88
|
+
name: sku.sku_name,
|
|
89
|
+
unit,
|
|
90
|
+
min_usd: minUsd,
|
|
91
|
+
max_usd: maxUsd,
|
|
92
|
+
role: tokenBased ? 'token' : addOn ? 'add_on' : 'output',
|
|
93
|
+
};
|
|
94
|
+
if (multipliers && Object.keys(multipliers).length > 0)
|
|
95
|
+
price.multipliers = multipliers;
|
|
96
|
+
if (typeof sku.min_charge_uc === 'number' && sku.min_charge_uc > 0 && !tokenBased) {
|
|
97
|
+
price.min_charge_usd = sku.min_charge_uc / 10_000 / CREDITS_PER_USD;
|
|
98
|
+
}
|
|
99
|
+
return price;
|
|
100
|
+
}
|
|
101
|
+
function buildIndex(skus) {
|
|
102
|
+
const models = new Map();
|
|
103
|
+
for (const sku of skus) {
|
|
104
|
+
if (!sku?.model_name || !['image', 'video', 'audio'].includes(sku.model_type))
|
|
105
|
+
continue;
|
|
106
|
+
const price = skuPrice(sku);
|
|
107
|
+
let model = models.get(sku.model_name);
|
|
108
|
+
if (!model) {
|
|
109
|
+
model = { id: sku.model_name, kind: sku.model_type, vendor: sku.vendor_slug, description: sku.description || undefined, prices: [] };
|
|
110
|
+
models.set(sku.model_name, model);
|
|
111
|
+
}
|
|
112
|
+
if (!model.description && sku.description)
|
|
113
|
+
model.description = sku.description;
|
|
114
|
+
if (price)
|
|
115
|
+
model.prices.push(price);
|
|
116
|
+
}
|
|
117
|
+
return models;
|
|
118
|
+
}
|
|
119
|
+
async function fetchPricing() {
|
|
120
|
+
const response = await fetchWithTimeout(`${controlBaseURL()}/web/api/models/pricing`, {
|
|
121
|
+
method: 'GET',
|
|
122
|
+
headers: { 'Accept': 'application/json', ...evoHeaders('pricing') },
|
|
123
|
+
}, timeoutFromEnv('EVOLINK_MCP_READ_TIMEOUT_MS', DEFAULT_READ_TIMEOUT_MS));
|
|
124
|
+
const body = await readJsonBody(response);
|
|
125
|
+
if (!response.ok || !Array.isArray(body.data)) {
|
|
126
|
+
throw new Error(`the pricing list returned HTTP ${response.status}`);
|
|
127
|
+
}
|
|
128
|
+
return { models: buildIndex(body.data), fetchedAt: Date.now() };
|
|
129
|
+
}
|
|
130
|
+
/** Image, video and audio models with their published unit prices; cached for five minutes, served stale for a day if a refresh fails. */
|
|
131
|
+
export async function getPricing() {
|
|
132
|
+
const now = Date.now();
|
|
133
|
+
if (cached && now - cached.fetchedAt < CACHE_TTL_MS)
|
|
134
|
+
return { ...cached, source: 'cache' };
|
|
135
|
+
try {
|
|
136
|
+
inflight ??= fetchPricing().finally(() => {
|
|
137
|
+
inflight = undefined;
|
|
138
|
+
});
|
|
139
|
+
cached = await inflight;
|
|
140
|
+
return { ...cached, source: 'live' };
|
|
141
|
+
}
|
|
142
|
+
catch (error) {
|
|
143
|
+
if (cached && now - cached.fetchedAt <= MAX_STALE_MS)
|
|
144
|
+
return { ...cached, source: 'stale-cache' };
|
|
145
|
+
throw error;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
export function resetPricingCacheForTests() {
|
|
149
|
+
cached = undefined;
|
|
150
|
+
inflight = undefined;
|
|
151
|
+
}
|
|
152
|
+
export function findPricedModel(models, id) {
|
|
153
|
+
const direct = models.get(id.trim());
|
|
154
|
+
if (direct)
|
|
155
|
+
return direct;
|
|
156
|
+
const lower = id.trim().toLowerCase();
|
|
157
|
+
for (const model of models.values())
|
|
158
|
+
if (model.id.toLowerCase() === lower)
|
|
159
|
+
return model;
|
|
160
|
+
return undefined;
|
|
161
|
+
}
|
|
162
|
+
export function formatPrice(price) {
|
|
163
|
+
const amount = price.min_usd === price.max_usd
|
|
164
|
+
? `$${formatUsd(price.min_usd)}`
|
|
165
|
+
: `$${formatUsd(price.min_usd)}–$${formatUsd(price.max_usd)}`;
|
|
166
|
+
return `${amount} per ${price.unit}`;
|
|
167
|
+
}
|
|
168
|
+
/** Lowest main unit price, for listings ("from $0.04 per image"). */
|
|
169
|
+
export function startingPrice(model) {
|
|
170
|
+
const outputs = model.prices.filter(price => price.role === 'output');
|
|
171
|
+
const pool = outputs.length > 0 ? outputs : model.prices;
|
|
172
|
+
return [...pool].sort((a, b) => a.min_usd - b.min_usd)[0];
|
|
173
|
+
}
|
|
174
|
+
const COUNT_PARAMS = ['n', 'num_images', 'number_of_images', 'image_count', 'count'];
|
|
175
|
+
const DURATION_PARAMS = ['duration', 'seconds', 'duration_seconds'];
|
|
176
|
+
const TIER_PARAMS = ['quality', 'resolution', 'size'];
|
|
177
|
+
const TIER_TOKEN = /\b(\d+(?:\.\d+)?k|\d{3,4}p)\b/gi;
|
|
178
|
+
function numberParam(input, names, spec) {
|
|
179
|
+
for (const name of names) {
|
|
180
|
+
const value = input[name];
|
|
181
|
+
if (typeof value === 'number' && Number.isFinite(value) && value > 0)
|
|
182
|
+
return { value, source: `input.${name}` };
|
|
183
|
+
if (typeof value === 'string' && value.trim() !== '' && Number.isFinite(Number(value)) && Number(value) > 0) {
|
|
184
|
+
return { value: Number(value), source: `input.${name}` };
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
for (const name of names) {
|
|
188
|
+
const fallback = spec?.params[name]?.default;
|
|
189
|
+
if (typeof fallback === 'number' && fallback > 0)
|
|
190
|
+
return { value: fallback, source: `default ${name}` };
|
|
191
|
+
}
|
|
192
|
+
return undefined;
|
|
193
|
+
}
|
|
194
|
+
function tierOf(name) {
|
|
195
|
+
return [...name.matchAll(TIER_TOKEN)].map(match => match[1].toLowerCase());
|
|
196
|
+
}
|
|
197
|
+
function countInputMedia(input, pattern) {
|
|
198
|
+
let count = 0;
|
|
199
|
+
for (const [key, value] of Object.entries(input)) {
|
|
200
|
+
if (!pattern.test(key))
|
|
201
|
+
continue;
|
|
202
|
+
if (Array.isArray(value))
|
|
203
|
+
count += value.filter(item => typeof item === 'string' && item).length;
|
|
204
|
+
else if (typeof value === 'string' && value)
|
|
205
|
+
count += 1;
|
|
206
|
+
}
|
|
207
|
+
return count;
|
|
208
|
+
}
|
|
209
|
+
function multiplierRange(price, tiers) {
|
|
210
|
+
if (!price.multipliers)
|
|
211
|
+
return [1, 1];
|
|
212
|
+
const entries = Object.entries(price.multipliers).filter(([, value]) => typeof value === 'number' && value > 0);
|
|
213
|
+
if (entries.length === 0)
|
|
214
|
+
return [1, 1];
|
|
215
|
+
const chosen = entries.find(([key]) => tiers.includes(key.toLowerCase()));
|
|
216
|
+
if (chosen)
|
|
217
|
+
return [chosen[1], chosen[1]];
|
|
218
|
+
const values = entries.map(([, value]) => value);
|
|
219
|
+
return [Math.min(...values), Math.max(...values)];
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Interim media estimate: published unit price × images or seconds, plus
|
|
223
|
+
* per-input-image charges. The gateway's own pre-charge at submit time is
|
|
224
|
+
* authoritative; this only tells the user what to expect.
|
|
225
|
+
*/
|
|
226
|
+
export function estimateCost(model, kind, input, spec) {
|
|
227
|
+
const estimate = { status: 'no_price', basis: [], possible_extras: [], notes: [] };
|
|
228
|
+
if (!model || model.prices.length === 0) {
|
|
229
|
+
estimate.notes.push('No price is published for this model, so no estimate is possible.');
|
|
230
|
+
return estimate;
|
|
231
|
+
}
|
|
232
|
+
const tiers = TIER_PARAMS
|
|
233
|
+
.map(name => input[name] ?? spec?.params[name]?.default)
|
|
234
|
+
.filter((value) => typeof value === 'string')
|
|
235
|
+
.map(value => value.toLowerCase());
|
|
236
|
+
const outputs = model.prices.filter(price => price.role === 'output');
|
|
237
|
+
if (outputs.length === 0) {
|
|
238
|
+
estimate.status = model.prices.some(price => price.role === 'token') ? 'token_billed' : 'no_price';
|
|
239
|
+
estimate.notes.push('This model is billed by tokens used, so the cost is only known after it runs.');
|
|
240
|
+
for (const price of model.prices)
|
|
241
|
+
estimate.basis.push(`${price.name}: ${formatPrice(price)}`);
|
|
242
|
+
return estimate;
|
|
243
|
+
}
|
|
244
|
+
// Pick the price tier the input asks for (e.g. "4K", "1080p"); untiered SKUs are the default tier.
|
|
245
|
+
let candidates = outputs;
|
|
246
|
+
if (tiers.length > 0) {
|
|
247
|
+
const matching = outputs.filter(price => tierOf(price.name).some(tier => tiers.includes(tier)));
|
|
248
|
+
const untiered = outputs.filter(price => tierOf(price.name).length === 0);
|
|
249
|
+
if (matching.length > 0)
|
|
250
|
+
candidates = matching;
|
|
251
|
+
else if (untiered.length > 0)
|
|
252
|
+
candidates = untiered;
|
|
253
|
+
}
|
|
254
|
+
let min = Infinity;
|
|
255
|
+
let max = 0;
|
|
256
|
+
for (const price of candidates) {
|
|
257
|
+
let quantity = 1;
|
|
258
|
+
let quantityText = '';
|
|
259
|
+
if (price.unit === 'image') {
|
|
260
|
+
const count = numberParam(input, COUNT_PARAMS, spec);
|
|
261
|
+
quantity = count?.value ?? 1;
|
|
262
|
+
quantityText = ` × ${quantity} image${quantity === 1 ? '' : 's'}${count ? ` (${count.source})` : ''}`;
|
|
263
|
+
}
|
|
264
|
+
else if (price.unit === 'second') {
|
|
265
|
+
const duration = numberParam(input, DURATION_PARAMS, spec);
|
|
266
|
+
if (!duration) {
|
|
267
|
+
estimate.status = 'needs_input';
|
|
268
|
+
estimate.notes.push(`${price.name} is billed per second; pass input.duration to get an estimate.`);
|
|
269
|
+
estimate.basis.push(`${price.name}: ${formatPrice(price)}`);
|
|
270
|
+
continue;
|
|
271
|
+
}
|
|
272
|
+
quantity = duration.value;
|
|
273
|
+
quantityText = ` × ${quantity} s (${duration.source})`;
|
|
274
|
+
}
|
|
275
|
+
else if (price.unit !== 'request') {
|
|
276
|
+
estimate.notes.push(`${price.name} is billed per ${price.unit}; it is not included in the range.`);
|
|
277
|
+
continue;
|
|
278
|
+
}
|
|
279
|
+
const [lowFactor, highFactor] = multiplierRange(price, tiers);
|
|
280
|
+
let low = price.min_usd * quantity * lowFactor;
|
|
281
|
+
let high = price.max_usd * quantity * highFactor;
|
|
282
|
+
if (price.min_charge_usd !== undefined) {
|
|
283
|
+
low = Math.max(low, price.min_charge_usd);
|
|
284
|
+
high = Math.max(high, price.min_charge_usd);
|
|
285
|
+
}
|
|
286
|
+
min = Math.min(min, low);
|
|
287
|
+
max = Math.max(max, high);
|
|
288
|
+
const factorText = highFactor !== 1 || lowFactor !== 1 ? ` × resolution factor ${lowFactor === highFactor ? lowFactor : `${lowFactor}–${highFactor}`}` : '';
|
|
289
|
+
estimate.basis.push(`${price.name}: ${formatPrice(price)}${quantityText}${factorText}`);
|
|
290
|
+
}
|
|
291
|
+
if (estimate.status === 'needs_input')
|
|
292
|
+
return estimate;
|
|
293
|
+
const mainCharge = min !== Infinity && max > 0;
|
|
294
|
+
// Per-image input charges that this input actually triggers; anything else is listed as a possible extra.
|
|
295
|
+
for (const price of model.prices.filter(item => item.role === 'add_on')) {
|
|
296
|
+
const used = price.unit === 'image' ? countInputMedia(input, /image|frame/i) : 0;
|
|
297
|
+
if (mainCharge && used > 0) {
|
|
298
|
+
min += price.min_usd * used;
|
|
299
|
+
max += price.max_usd * used;
|
|
300
|
+
estimate.basis.push(`${price.name}: ${formatPrice(price)} × ${used} input image${used === 1 ? '' : 's'}`);
|
|
301
|
+
}
|
|
302
|
+
else {
|
|
303
|
+
estimate.possible_extras.push(`${price.name}: ${formatPrice(price)}`);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
if (!mainCharge)
|
|
307
|
+
return estimate;
|
|
308
|
+
estimate.status = 'estimated';
|
|
309
|
+
estimate.min_usd = min;
|
|
310
|
+
estimate.max_usd = max;
|
|
311
|
+
estimate.min_credits = min * CREDITS_PER_USD;
|
|
312
|
+
estimate.max_credits = max * CREDITS_PER_USD;
|
|
313
|
+
if (candidates.length < outputs.length) {
|
|
314
|
+
estimate.notes.push(`Price tier chosen from ${TIER_PARAMS.filter(name => input[name] !== undefined).map(name => `input.${name}`).join(', ') || 'the default settings'}.`);
|
|
315
|
+
}
|
|
316
|
+
else if (outputs.length > 1) {
|
|
317
|
+
estimate.notes.push('The range covers all output tiers; set the quality or resolution to narrow it.');
|
|
318
|
+
}
|
|
319
|
+
return estimate;
|
|
320
|
+
}
|
|
321
|
+
export function formatEstimateRange(estimate) {
|
|
322
|
+
if (estimate.min_usd === undefined || estimate.max_usd === undefined)
|
|
323
|
+
return undefined;
|
|
324
|
+
const usd = Math.abs(estimate.max_usd - estimate.min_usd) < 1e-9
|
|
325
|
+
? `$${formatUsd(estimate.max_usd)}`
|
|
326
|
+
: `$${formatUsd(estimate.min_usd)}–$${formatUsd(estimate.max_usd)}`;
|
|
327
|
+
const credits = Math.abs((estimate.max_credits ?? 0) - (estimate.min_credits ?? 0)) < 1e-6
|
|
328
|
+
? `${Number((estimate.max_credits ?? 0).toFixed(2))}`
|
|
329
|
+
: `${Number((estimate.min_credits ?? 0).toFixed(2))}–${Number((estimate.max_credits ?? 0).toFixed(2))}`;
|
|
330
|
+
return `${usd} (${credits} credits)`;
|
|
331
|
+
}
|
|
332
|
+
//# sourceMappingURL=pricing-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pricing-client.js","sourceRoot":"","sources":["../../../../../core/src/services/pricing-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare const MAX_UPLOAD_BYTES: number;
|
|
2
|
+
export interface LocalUploadInfo {
|
|
3
|
+
realPath: string;
|
|
4
|
+
size: number;
|
|
5
|
+
mimeType: string;
|
|
6
|
+
}
|
|
7
|
+
export interface Base64UploadInfo {
|
|
8
|
+
mimeType: string;
|
|
9
|
+
decodedBytes: number;
|
|
10
|
+
/** What to send: files-api takes the type from a Data URL prefix, but only guesses from raw base64. */
|
|
11
|
+
dataUrl: string;
|
|
12
|
+
}
|
|
13
|
+
export declare function inspectLocalUpload(filePath: string, allowedDirectories?: string | undefined): Promise<LocalUploadInfo>;
|
|
14
|
+
export declare function inspectBase64Upload(value: string, declaredMime?: string): Base64UploadInfo;
|
|
15
|
+
export declare function validateRemoteUploadURL(value: string): string;
|
|
16
|
+
export declare function validateUploadDestination(uploadPath?: string, fileName?: string): void;
|
|
17
|
+
//# sourceMappingURL=upload-policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upload-policy.d.ts","sourceRoot":"","sources":["../../../../../core/src/services/upload-policy.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,gBAAgB,QAAoB,CAAC;AAgBlD,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,uGAAuG;IACvG,OAAO,EAAE,MAAM,CAAC;CACjB;AAuCD,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,MAAM,EAChB,kBAAkB,qBAA0C,GAC3D,OAAO,CAAC,eAAe,CAAC,CAoC1B;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,gBAAgB,CA6B1F;AAWD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAgB7D;AAED,wBAAgB,yBAAyB,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAStF"}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { open, realpath, stat } from 'node:fs/promises';
|
|
2
|
+
import { isIP } from 'node:net';
|
|
3
|
+
import { delimiter, extname, isAbsolute, relative, resolve, } from 'node:path';
|
|
4
|
+
export const MAX_UPLOAD_BYTES = 100 * 1024 * 1024;
|
|
5
|
+
const MIME_BY_EXTENSION = {
|
|
6
|
+
'.jpg': 'image/jpeg', '.jpeg': 'image/jpeg',
|
|
7
|
+
'.png': 'image/png', '.gif': 'image/gif', '.webp': 'image/webp',
|
|
8
|
+
'.mp3': 'audio/mpeg', '.wav': 'audio/wav', '.flac': 'audio/flac',
|
|
9
|
+
'.aac': 'audio/aac', '.ogg': 'audio/ogg', '.m4a': 'audio/mp4', '.opus': 'audio/opus',
|
|
10
|
+
'.mp4': 'video/mp4', '.mov': 'video/quicktime', '.avi': 'video/x-msvideo',
|
|
11
|
+
'.mkv': 'video/x-matroska', '.webm': 'video/webm', '.flv': 'video/x-flv',
|
|
12
|
+
'.wmv': 'video/x-ms-wmv', '.ts': 'video/mp2t', '.m4v': 'video/mp4',
|
|
13
|
+
'.3gp': 'video/3gpp',
|
|
14
|
+
};
|
|
15
|
+
const ALLOWED_MIME_TYPES = new Set(Object.values(MIME_BY_EXTENSION));
|
|
16
|
+
const ASF_HEADER = Buffer.from('3026b2758e66cf11a6d900aa0062ce6c', 'hex');
|
|
17
|
+
function startsWith(buffer, signature) {
|
|
18
|
+
const expected = typeof signature === 'string' ? Buffer.from(signature) : signature;
|
|
19
|
+
return buffer.subarray(0, expected.length).equals(expected);
|
|
20
|
+
}
|
|
21
|
+
function hasFtyp(buffer) {
|
|
22
|
+
return buffer.length >= 12 && buffer.subarray(4, 8).toString('ascii') === 'ftyp';
|
|
23
|
+
}
|
|
24
|
+
function matchesMimeSignature(mime, buffer) {
|
|
25
|
+
switch (mime) {
|
|
26
|
+
case 'image/jpeg': return buffer[0] === 0xff && buffer[1] === 0xd8 && buffer[2] === 0xff;
|
|
27
|
+
case 'image/png': return startsWith(buffer, Buffer.from('89504e470d0a1a0a', 'hex'));
|
|
28
|
+
case 'image/gif': return startsWith(buffer, 'GIF87a') || startsWith(buffer, 'GIF89a');
|
|
29
|
+
case 'image/webp': return startsWith(buffer, 'RIFF') && buffer.subarray(8, 12).toString('ascii') === 'WEBP';
|
|
30
|
+
case 'audio/mpeg': return startsWith(buffer, 'ID3') || (buffer[0] === 0xff && (buffer[1] & 0xe0) === 0xe0);
|
|
31
|
+
case 'audio/wav': return startsWith(buffer, 'RIFF') && buffer.subarray(8, 12).toString('ascii') === 'WAVE';
|
|
32
|
+
case 'audio/flac': return startsWith(buffer, 'fLaC');
|
|
33
|
+
case 'audio/aac': return buffer[0] === 0xff && (buffer[1] & 0xf6) === 0xf0;
|
|
34
|
+
case 'audio/ogg': return startsWith(buffer, 'OggS');
|
|
35
|
+
case 'audio/opus': return startsWith(buffer, 'OggS') && buffer.includes(Buffer.from('OpusHead'));
|
|
36
|
+
case 'audio/mp4': return hasFtyp(buffer);
|
|
37
|
+
case 'video/mp4':
|
|
38
|
+
case 'video/quicktime':
|
|
39
|
+
case 'video/3gpp': return hasFtyp(buffer);
|
|
40
|
+
case 'video/x-msvideo': return startsWith(buffer, 'RIFF') && buffer.subarray(8, 12).toString('ascii') === 'AVI ';
|
|
41
|
+
case 'video/x-matroska':
|
|
42
|
+
case 'video/webm': return startsWith(buffer, Buffer.from('1a45dfa3', 'hex'));
|
|
43
|
+
case 'video/x-flv': return startsWith(buffer, 'FLV');
|
|
44
|
+
case 'video/x-ms-wmv': return startsWith(buffer, ASF_HEADER);
|
|
45
|
+
case 'video/mp2t': return buffer[0] === 0x47 || buffer[188] === 0x47;
|
|
46
|
+
default: return false;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function withinRoot(candidate, root) {
|
|
50
|
+
const pathFromRoot = relative(root, candidate);
|
|
51
|
+
return pathFromRoot === '' || (!pathFromRoot.startsWith('..') && !isAbsolute(pathFromRoot));
|
|
52
|
+
}
|
|
53
|
+
export async function inspectLocalUpload(filePath, allowedDirectories = process.env.EVOLINK_UPLOAD_ALLOWED_DIRS) {
|
|
54
|
+
if (!isAbsolute(filePath)) {
|
|
55
|
+
throw new Error('file_path must be absolute');
|
|
56
|
+
}
|
|
57
|
+
const configuredRoots = (allowedDirectories ?? '').split(delimiter).map(value => value.trim()).filter(Boolean);
|
|
58
|
+
if (configuredRoots.length === 0) {
|
|
59
|
+
throw new Error('local uploads are disabled; set EVOLINK_UPLOAD_ALLOWED_DIRS to explicit trusted directories');
|
|
60
|
+
}
|
|
61
|
+
if (configuredRoots.some(root => !isAbsolute(root))) {
|
|
62
|
+
throw new Error('EVOLINK_UPLOAD_ALLOWED_DIRS may contain only absolute directories');
|
|
63
|
+
}
|
|
64
|
+
const candidate = await realpath(resolve(filePath));
|
|
65
|
+
const roots = await Promise.all(configuredRoots.map(root => realpath(resolve(root))));
|
|
66
|
+
if (!roots.some(root => withinRoot(candidate, root))) {
|
|
67
|
+
throw new Error('file_path resolves outside EVOLINK_UPLOAD_ALLOWED_DIRS');
|
|
68
|
+
}
|
|
69
|
+
const fileStat = await stat(candidate);
|
|
70
|
+
if (!fileStat.isFile())
|
|
71
|
+
throw new Error('file_path must resolve to a regular file');
|
|
72
|
+
if (fileStat.size <= 0 || fileStat.size > MAX_UPLOAD_BYTES) {
|
|
73
|
+
throw new Error(`local file size must be between 1 byte and ${MAX_UPLOAD_BYTES} bytes`);
|
|
74
|
+
}
|
|
75
|
+
const mimeType = MIME_BY_EXTENSION[extname(candidate).toLowerCase()];
|
|
76
|
+
if (!mimeType)
|
|
77
|
+
throw new Error('local file extension is not an allowed image, audio, or video type');
|
|
78
|
+
const handle = await open(candidate, 'r');
|
|
79
|
+
try {
|
|
80
|
+
const header = Buffer.alloc(512);
|
|
81
|
+
const { bytesRead } = await handle.read(header, 0, header.length, 0);
|
|
82
|
+
if (!matchesMimeSignature(mimeType, header.subarray(0, bytesRead))) {
|
|
83
|
+
throw new Error(`local file content does not match declared MIME type ${mimeType}`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
finally {
|
|
87
|
+
await handle.close();
|
|
88
|
+
}
|
|
89
|
+
return { realPath: candidate, size: fileStat.size, mimeType };
|
|
90
|
+
}
|
|
91
|
+
export function inspectBase64Upload(value, declaredMime) {
|
|
92
|
+
let payload = value.trim();
|
|
93
|
+
let mimeType = declaredMime?.trim().toLowerCase();
|
|
94
|
+
const dataUrl = payload.match(/^data:([^;,]+);base64,([\s\S]+)$/i);
|
|
95
|
+
if (dataUrl) {
|
|
96
|
+
const dataMime = dataUrl[1].trim().toLowerCase();
|
|
97
|
+
if (mimeType && mimeType !== dataMime)
|
|
98
|
+
throw new Error('mime_type conflicts with the base64 Data URL');
|
|
99
|
+
mimeType = dataMime;
|
|
100
|
+
payload = dataUrl[2];
|
|
101
|
+
}
|
|
102
|
+
if (!mimeType)
|
|
103
|
+
throw new Error('mime_type is required for raw base64_data');
|
|
104
|
+
if (!ALLOWED_MIME_TYPES.has(mimeType))
|
|
105
|
+
throw new Error(`MIME type ${mimeType} is not allowed`);
|
|
106
|
+
const compact = payload.replaceAll(/\s/g, '');
|
|
107
|
+
if (!compact || !/^[A-Za-z0-9+/]*={0,2}$/.test(compact) || compact.length % 4 === 1) {
|
|
108
|
+
throw new Error('base64_data is not valid base64');
|
|
109
|
+
}
|
|
110
|
+
const padding = compact.endsWith('==') ? 2 : compact.endsWith('=') ? 1 : 0;
|
|
111
|
+
const decodedBytes = Math.floor(compact.length * 3 / 4) - padding;
|
|
112
|
+
if (decodedBytes <= 0 || decodedBytes > MAX_UPLOAD_BYTES) {
|
|
113
|
+
throw new Error(`decoded base64 size must be between 1 byte and ${MAX_UPLOAD_BYTES} bytes`);
|
|
114
|
+
}
|
|
115
|
+
const header = Buffer.from(compact.slice(0, 1_024), 'base64');
|
|
116
|
+
if (!matchesMimeSignature(mimeType, header)) {
|
|
117
|
+
throw new Error(`base64 content does not match declared MIME type ${mimeType}`);
|
|
118
|
+
}
|
|
119
|
+
// files-api decodes with Go's StdEncoding: no whitespace, and the '=' padding is required.
|
|
120
|
+
const padded = compact + '='.repeat((4 - (compact.length % 4)) % 4);
|
|
121
|
+
return { mimeType, decodedBytes, dataUrl: `data:${mimeType};base64,${padded}` };
|
|
122
|
+
}
|
|
123
|
+
function isPrivateIPv4(host) {
|
|
124
|
+
const parts = host.split('.').map(Number);
|
|
125
|
+
if (parts.length !== 4 || parts.some(value => !Number.isInteger(value)))
|
|
126
|
+
return false;
|
|
127
|
+
return parts[0] === 10 || parts[0] === 127 || parts[0] === 0
|
|
128
|
+
|| (parts[0] === 169 && parts[1] === 254)
|
|
129
|
+
|| (parts[0] === 172 && parts[1] >= 16 && parts[1] <= 31)
|
|
130
|
+
|| (parts[0] === 192 && parts[1] === 168);
|
|
131
|
+
}
|
|
132
|
+
export function validateRemoteUploadURL(value) {
|
|
133
|
+
let parsed;
|
|
134
|
+
try {
|
|
135
|
+
parsed = new URL(value);
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
throw new Error('file_url must be a valid absolute URL');
|
|
139
|
+
}
|
|
140
|
+
if (parsed.protocol !== 'https:' || parsed.username || parsed.password) {
|
|
141
|
+
throw new Error('file_url must use HTTPS and must not contain credentials');
|
|
142
|
+
}
|
|
143
|
+
const hostname = parsed.hostname.replace(/^\[|\]$/g, '').toLowerCase();
|
|
144
|
+
if (hostname === 'localhost' || hostname.endsWith('.localhost') || isPrivateIPv4(hostname)
|
|
145
|
+
|| (isIP(hostname) === 6 && (hostname === '::1' || hostname.startsWith('fc') || hostname.startsWith('fd') || hostname.startsWith('fe80:')))) {
|
|
146
|
+
throw new Error('file_url must not target a loopback or private address');
|
|
147
|
+
}
|
|
148
|
+
return parsed.toString();
|
|
149
|
+
}
|
|
150
|
+
export function validateUploadDestination(uploadPath, fileName) {
|
|
151
|
+
if (uploadPath) {
|
|
152
|
+
if (uploadPath.length > 256 || isAbsolute(uploadPath) || uploadPath.split(/[\\/]+/).some(part => part === '..')) {
|
|
153
|
+
throw new Error('upload_path must be a relative server path without parent traversal');
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
if (fileName && (fileName.length > 255 || fileName.includes('/') || fileName.includes('\\') || fileName === '.' || fileName === '..')) {
|
|
157
|
+
throw new Error('file_name must be a plain file name without path separators');
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=upload-policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upload-policy.js","sourceRoot":"","sources":["../../../../../core/src/services/upload-policy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-balance.d.ts","sourceRoot":"","sources":["../../../../../core/src/tools/check-balance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAUjD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,GAAG,IAAI,CAiElF"}
|