opencode-pollinations-plugin 6.1.0-beta.1 → 6.1.0-beta.11
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/README.md +140 -87
- package/dist/index.js +33 -154
- package/dist/server/commands.d.ts +2 -0
- package/dist/server/commands.js +106 -60
- package/dist/server/config.d.ts +27 -23
- package/dist/server/config.js +24 -50
- package/dist/server/generate-config.d.ts +3 -30
- package/dist/server/generate-config.js +172 -100
- package/dist/server/index.d.ts +2 -1
- package/dist/server/index.js +124 -149
- package/dist/server/pollinations-api.d.ts +11 -0
- package/dist/server/pollinations-api.js +20 -0
- package/dist/server/proxy.js +187 -149
- package/dist/server/quota.d.ts +8 -0
- package/dist/server/quota.js +106 -61
- package/dist/server/toast.d.ts +3 -0
- package/dist/server/toast.js +16 -0
- package/dist/tools/design/gen_diagram.d.ts +2 -0
- package/dist/tools/design/gen_diagram.js +94 -0
- package/dist/tools/design/gen_palette.d.ts +2 -0
- package/dist/tools/design/gen_palette.js +182 -0
- package/dist/tools/design/gen_qrcode.d.ts +2 -0
- package/dist/tools/design/gen_qrcode.js +50 -0
- package/dist/tools/index.d.ts +22 -0
- package/dist/tools/index.js +81 -0
- package/dist/tools/pollinations/deepsearch.d.ts +7 -0
- package/dist/tools/pollinations/deepsearch.js +80 -0
- package/dist/tools/pollinations/gen_audio.d.ts +18 -0
- package/dist/tools/pollinations/gen_audio.js +204 -0
- package/dist/tools/pollinations/gen_image.d.ts +13 -0
- package/dist/tools/pollinations/gen_image.js +239 -0
- package/dist/tools/pollinations/gen_music.d.ts +14 -0
- package/dist/tools/pollinations/gen_music.js +139 -0
- package/dist/tools/pollinations/gen_video.d.ts +16 -0
- package/dist/tools/pollinations/gen_video.js +222 -0
- package/dist/tools/pollinations/search_crawl_scrape.d.ts +7 -0
- package/dist/tools/pollinations/search_crawl_scrape.js +85 -0
- package/dist/tools/pollinations/shared.d.ts +170 -0
- package/dist/tools/pollinations/shared.js +454 -0
- package/dist/tools/pollinations/transcribe_audio.d.ts +17 -0
- package/dist/tools/pollinations/transcribe_audio.js +235 -0
- package/dist/tools/power/extract_audio.d.ts +2 -0
- package/dist/tools/power/extract_audio.js +180 -0
- package/dist/tools/power/extract_frames.d.ts +2 -0
- package/dist/tools/power/extract_frames.js +240 -0
- package/dist/tools/power/file_to_url.d.ts +2 -0
- package/dist/tools/power/file_to_url.js +217 -0
- package/dist/tools/power/remove_background.d.ts +2 -0
- package/dist/tools/power/remove_background.js +365 -0
- package/dist/tools/power/rmbg_keys.d.ts +2 -0
- package/dist/tools/power/rmbg_keys.js +78 -0
- package/dist/tools/shared.d.ts +30 -0
- package/dist/tools/shared.js +74 -0
- package/package.json +9 -3
- package/dist/server/models-seed.d.ts +0 -18
- package/dist/server/models-seed.js +0 -55
package/dist/server/commands.js
CHANGED
|
@@ -57,6 +57,7 @@ export async function checkKeyPermissions(key) {
|
|
|
57
57
|
}
|
|
58
58
|
// === CONSTANTS & PRICING ===
|
|
59
59
|
const TIER_LIMITS = {
|
|
60
|
+
microbe: { pollen: 0.1, emoji: '🦠' },
|
|
60
61
|
spore: { pollen: 1, emoji: '🦠' },
|
|
61
62
|
seed: { pollen: 3, emoji: '🌱' },
|
|
62
63
|
flower: { pollen: 10, emoji: '🌸' },
|
|
@@ -130,6 +131,10 @@ function calculateCurrentPeriodStats(usage, lastReset, tierLimit) {
|
|
|
130
131
|
};
|
|
131
132
|
}
|
|
132
133
|
// === COMMAND HANDLER ===
|
|
134
|
+
let globalClient = null;
|
|
135
|
+
export function setClientForCommands(client) {
|
|
136
|
+
globalClient = client;
|
|
137
|
+
}
|
|
133
138
|
export async function handleCommand(command) {
|
|
134
139
|
const parts = command.trim().split(/\s+/);
|
|
135
140
|
if (!parts[0].startsWith('/poll')) {
|
|
@@ -150,6 +155,13 @@ export async function handleCommand(command) {
|
|
|
150
155
|
return handleConfigCommand(args);
|
|
151
156
|
case 'help':
|
|
152
157
|
return handleHelpCommand();
|
|
158
|
+
case 'addKey': // External trigger
|
|
159
|
+
// UI Pollution Fix: User hates appendPrompt.
|
|
160
|
+
// Just return a message telling them to use the tool.
|
|
161
|
+
return {
|
|
162
|
+
handled: true,
|
|
163
|
+
response: "💡 Pour ajouter une clé : Utilisez l'outil `rmbg_keys`\nExemple : `rmbg_keys action=add key=bkgc_...`"
|
|
164
|
+
};
|
|
153
165
|
default:
|
|
154
166
|
return {
|
|
155
167
|
handled: true,
|
|
@@ -202,7 +214,7 @@ async function handleModeCommand(args) {
|
|
|
202
214
|
return { handled: true, error: `❌ Erreur de vérification: ${e.message}` };
|
|
203
215
|
}
|
|
204
216
|
}
|
|
205
|
-
// Allow switch (if
|
|
217
|
+
// Allow switch (if alwaysfree or manual, or verified pro)
|
|
206
218
|
saveConfig({ mode: mode });
|
|
207
219
|
const config = loadConfig();
|
|
208
220
|
if (config.gui.status !== 'none') {
|
|
@@ -264,36 +276,32 @@ async function handleUsageCommand(args) {
|
|
|
264
276
|
}
|
|
265
277
|
}
|
|
266
278
|
function handleFallbackCommand(args) {
|
|
267
|
-
const [
|
|
268
|
-
if (!
|
|
279
|
+
const [main, agent] = args;
|
|
280
|
+
if (!main) {
|
|
269
281
|
const config = loadConfig();
|
|
282
|
+
const freeConfig = `Free: main=${config.fallbacks.free.main}, agent=${config.fallbacks.free.agent}`;
|
|
283
|
+
const enterConfig = `Enter: agent=${config.fallbacks.enter.agent}`;
|
|
270
284
|
return {
|
|
271
285
|
handled: true,
|
|
272
|
-
response: `Fallbacks actuels:\n
|
|
286
|
+
response: `Fallbacks actuels:\n${freeConfig}\n${enterConfig}`
|
|
273
287
|
};
|
|
274
288
|
}
|
|
289
|
+
// Default behavior for "/poll fallback <model> <agent>" is setting FREE fallbacks
|
|
290
|
+
// User needs to use commands (maybe add /poll fallback enter ...) later
|
|
291
|
+
// For now, map to Free Fallback as it's the primary Safety Net
|
|
275
292
|
const config = loadConfig();
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
if (mode === 'pro' && model) {
|
|
286
|
-
saveConfig({
|
|
287
|
-
fallbacks: { ...config.fallbacks, pro: model }
|
|
288
|
-
});
|
|
289
|
-
return {
|
|
290
|
-
handled: true,
|
|
291
|
-
response: `✅ Fallback Pro configuré: ${model}`
|
|
292
|
-
};
|
|
293
|
-
}
|
|
293
|
+
saveConfig({
|
|
294
|
+
fallbacks: {
|
|
295
|
+
...config.fallbacks,
|
|
296
|
+
free: {
|
|
297
|
+
main: main,
|
|
298
|
+
agent: agent || config.fallbacks.free.agent
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
});
|
|
294
302
|
return {
|
|
295
303
|
handled: true,
|
|
296
|
-
|
|
304
|
+
response: `✅ Fallback (Free) configuré: main=${main}, agent=${agent || config.fallbacks.free.agent}`
|
|
297
305
|
};
|
|
298
306
|
}
|
|
299
307
|
async function handleConnectCommand(args) {
|
|
@@ -307,15 +315,15 @@ async function handleConnectCommand(args) {
|
|
|
307
315
|
// 1. Universal Validation (No Syntax Check) - Functional Check
|
|
308
316
|
emitStatusToast('info', 'Vérification de la clé...', 'Pollinations Config');
|
|
309
317
|
try {
|
|
310
|
-
const models = await generatePollinationsConfig(key);
|
|
311
|
-
// 2. Check if we got
|
|
312
|
-
const
|
|
313
|
-
if (
|
|
318
|
+
const models = await generatePollinationsConfig(key, true);
|
|
319
|
+
// 2. Check if we got Enterprise models
|
|
320
|
+
const enterpriseModels = models.filter(m => m.id.startsWith('enter/'));
|
|
321
|
+
if (enterpriseModels.length > 0) {
|
|
314
322
|
// SUCCESS
|
|
315
323
|
saveConfig({ apiKey: key }); // Don't force mode 'pro'. Let user decide.
|
|
316
324
|
const masked = key.substring(0, 6) + '...';
|
|
317
325
|
// Count Paid Only models found
|
|
318
|
-
const diamondCount =
|
|
326
|
+
const diamondCount = enterpriseModels.filter(m => m.name.includes('💎')).length;
|
|
319
327
|
// CHECK RESTRICTIONS: Strict Check (Usage + Profile + Balance)
|
|
320
328
|
let forcedModeMsg = "";
|
|
321
329
|
let isLimited = false;
|
|
@@ -340,10 +348,10 @@ async function handleConnectCommand(args) {
|
|
|
340
348
|
else {
|
|
341
349
|
saveConfig({ apiKey: key, keyHasAccessToProfile: true }); // Let user keep current mode or default
|
|
342
350
|
}
|
|
343
|
-
emitStatusToast('success', `Clé Valide! (${
|
|
351
|
+
emitStatusToast('success', `Clé Valide! (${enterpriseModels.length} modèles Pro débloqués)`, 'Pollinations Config');
|
|
344
352
|
return {
|
|
345
353
|
handled: true,
|
|
346
|
-
response: `✅ **Connexion Réussie!**\n- Clé: \`${masked}\`\n- Modèles Débloqués: ${
|
|
354
|
+
response: `✅ **Connexion Réussie!**\n- Clé: \`${masked}\`\n- Modèles Débloqués: ${enterpriseModels.length} (dont ${diamondCount} 💎 Paid)${forcedModeMsg}`
|
|
347
355
|
};
|
|
348
356
|
}
|
|
349
357
|
else {
|
|
@@ -355,8 +363,18 @@ async function handleConnectCommand(args) {
|
|
|
355
363
|
// Wait, generate-config falls back to providing a list containing "[Enter] GPT-4o (Fallback)" if fetch failed.
|
|
356
364
|
// So we need to detect if it's a "REAL" fetch or a "FALLBACK" fetch.
|
|
357
365
|
// The fallback models have `variants: {}` usually, but real ones might too.
|
|
358
|
-
//
|
|
359
|
-
|
|
366
|
+
// A better check: The fallback list is hardcoded in generate-config.ts catch block.
|
|
367
|
+
// Let's modify generate-config to return EMPTY list on error?
|
|
368
|
+
// Or just check if the returned models work?
|
|
369
|
+
// Simplest: If `generatePollinationsConfig` returns any model starting with `enter/` that includes "(Fallback)" in name, we assume failure?
|
|
370
|
+
// "GPT-4o (Fallback)" is the name.
|
|
371
|
+
const isFallback = models.some(m => m.name.includes('(Fallback)') && m.id.startsWith('enter/'));
|
|
372
|
+
if (isFallback) {
|
|
373
|
+
throw new Error("Clé rejetée par l'API (Accès refusé ou invalide).");
|
|
374
|
+
}
|
|
375
|
+
// If we are here, we got no enter models, or empty list?
|
|
376
|
+
// If key is valid but has no access?
|
|
377
|
+
throw new Error("Aucun modèle Enterprise détecté pour cette clé.");
|
|
360
378
|
}
|
|
361
379
|
}
|
|
362
380
|
catch (e) {
|
|
@@ -415,47 +433,49 @@ function handleConfigCommand(args) {
|
|
|
415
433
|
saveConfig({ thresholds: { ...config.thresholds, tier: threshold } });
|
|
416
434
|
return { handled: true, response: `✅ threshold_tier = ${threshold}%` };
|
|
417
435
|
}
|
|
418
|
-
if (key === '
|
|
436
|
+
if (key === 'threshold_wallet' && value) {
|
|
419
437
|
const threshold = parseInt(value);
|
|
420
438
|
if (isNaN(threshold) || threshold < 0 || threshold > 100) {
|
|
421
439
|
return { handled: true, error: 'Valeur entre 0 et 100 requise' };
|
|
422
440
|
}
|
|
423
441
|
const config = loadConfig();
|
|
424
|
-
saveConfig({ thresholds: { ...config.thresholds,
|
|
425
|
-
return { handled: true, response: `✅
|
|
426
|
-
}
|
|
427
|
-
if (key === 'threshold_wallet_stop' && value) {
|
|
428
|
-
const stopValue = parseFloat(value);
|
|
429
|
-
if (isNaN(stopValue) || stopValue < 0) {
|
|
430
|
-
return { handled: true, error: 'Valeur $ positive requise' };
|
|
431
|
-
}
|
|
432
|
-
const config = loadConfig();
|
|
433
|
-
saveConfig({ thresholds: { ...config.thresholds, wallet_stop: stopValue } });
|
|
434
|
-
return { handled: true, response: `✅ threshold_wallet_stop = $${stopValue}` };
|
|
442
|
+
saveConfig({ thresholds: { ...config.thresholds, wallet: threshold } });
|
|
443
|
+
return { handled: true, response: `✅ threshold_wallet = ${threshold}%` };
|
|
435
444
|
}
|
|
436
445
|
if (key === 'status_bar' && value) {
|
|
437
446
|
const enabled = value === 'true';
|
|
438
447
|
saveConfig({ statusBar: enabled });
|
|
439
448
|
return { handled: true, response: `✅ status_bar = ${enabled}` };
|
|
440
449
|
}
|
|
450
|
+
if (key === 'cost_estimator' && value) {
|
|
451
|
+
const enabled = value === 'true';
|
|
452
|
+
const config = loadConfig();
|
|
453
|
+
saveConfig({ ...config, costEstimator: enabled });
|
|
454
|
+
return { handled: true, response: `✅ cost_estimator = ${enabled}` };
|
|
455
|
+
}
|
|
441
456
|
return {
|
|
442
457
|
handled: true,
|
|
443
|
-
error: `Clé inconnue: ${key}. Clés: status_gui, logs_gui, threshold_tier,
|
|
458
|
+
error: `Clé inconnue: ${key}. Clés: status_gui, logs_gui, threshold_tier, threshold_wallet, status_bar, cost_estimator`
|
|
444
459
|
};
|
|
445
460
|
}
|
|
446
461
|
function handleHelpCommand() {
|
|
447
462
|
const help = `
|
|
448
|
-
### 🌸 Pollinations Plugin - Commandes
|
|
463
|
+
### 🌸 Pollinations Plugin - Commandes V6
|
|
449
464
|
|
|
465
|
+
**Mode & Usage**
|
|
450
466
|
- **\`/pollinations mode [mode]\`**: Change le mode (manual, alwaysfree, pro).
|
|
451
467
|
- **\`/pollinations usage [full]\`**: Affiche le dashboard (full = détail).
|
|
452
|
-
- **\`/pollinations fallback <main> [agent]\`**: Configure le Safety Net
|
|
468
|
+
- **\`/pollinations fallback <main> [agent]\`**: Configure le Safety Net.
|
|
469
|
+
|
|
470
|
+
**Configuration**
|
|
453
471
|
- **\`/pollinations config [key] [value]\`**:
|
|
454
|
-
- \`status_gui\`: none, alert, all
|
|
455
|
-
- \`logs_gui\`: none, error, verbose
|
|
456
|
-
- \`threshold_tier\`: 0-100
|
|
457
|
-
- \`
|
|
458
|
-
- \`
|
|
472
|
+
- \`status_gui\`: none, alert, all
|
|
473
|
+
- \`logs_gui\`: none, error, verbose
|
|
474
|
+
- \`threshold_tier\` / \`threshold_wallet\`: 0-100
|
|
475
|
+
- \`status_bar\`: true/false
|
|
476
|
+
- \`cost_estimator\`: true/false (show cost in outputs)
|
|
477
|
+
|
|
478
|
+
> 💡 **RMBG keys**: Use the \`rmbg_keys\` tool (works with any model).
|
|
459
479
|
`.trim();
|
|
460
480
|
return { handled: true, response: help };
|
|
461
481
|
}
|
|
@@ -463,16 +483,42 @@ function handleHelpCommand() {
|
|
|
463
483
|
export function createCommandHooks() {
|
|
464
484
|
return {
|
|
465
485
|
'tui.command.execute': async (input, output) => {
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
486
|
+
if (!input.command.startsWith('/pollinations')) {
|
|
487
|
+
return;
|
|
488
|
+
}
|
|
489
|
+
try {
|
|
490
|
+
// Parse command
|
|
491
|
+
const rawArgs = input.command.replace('/pollinations', '').trim();
|
|
492
|
+
const result = await handleCommand(rawArgs);
|
|
493
|
+
if (result.handled) {
|
|
494
|
+
if (result.error) {
|
|
495
|
+
output.error = `❌ **Erreur:** ${result.error}`;
|
|
496
|
+
}
|
|
497
|
+
else if (result.response) {
|
|
498
|
+
output.response = result.response;
|
|
499
|
+
}
|
|
500
|
+
// If no response and no error, assume handled silently (like appendPrompt)
|
|
474
501
|
}
|
|
475
502
|
}
|
|
503
|
+
catch (err) {
|
|
504
|
+
output.error = `❌ **Erreur Critique:** ${err.message}`;
|
|
505
|
+
}
|
|
506
|
+
},
|
|
507
|
+
// Hook for UI Commands (Palette / Buttons)
|
|
508
|
+
'command.execute.before': async (input, output) => {
|
|
509
|
+
const cmd = input.command;
|
|
510
|
+
if (cmd === 'pollinations.addKey') {
|
|
511
|
+
handleCommand('addKey'); // Return help message
|
|
512
|
+
}
|
|
513
|
+
else if (cmd === 'pollinations.usage') {
|
|
514
|
+
const res = await handleCommand('usage');
|
|
515
|
+
if (res.response)
|
|
516
|
+
globalClient?.tui.showToast({ title: "Pollinations Usage", metadata: { type: 'info', message: "Voir logs pour usage détaillé" } });
|
|
517
|
+
}
|
|
518
|
+
else if (cmd === 'pollinations.mode') {
|
|
519
|
+
// UI Pollution Fix: SILENCE.
|
|
520
|
+
// User explicitly requested NO messages.
|
|
521
|
+
}
|
|
476
522
|
}
|
|
477
523
|
};
|
|
478
524
|
}
|
package/dist/server/config.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export interface
|
|
1
|
+
export interface PollinationsConfigV5 {
|
|
2
2
|
version: string | number;
|
|
3
|
-
mode: 'manual' | '
|
|
3
|
+
mode: 'manual' | 'alwaysfree' | 'pro';
|
|
4
4
|
apiKey?: string;
|
|
5
5
|
keyHasAccessToProfile?: boolean;
|
|
6
6
|
gui: {
|
|
@@ -9,24 +9,27 @@ export interface PollinationsConfigV6 {
|
|
|
9
9
|
};
|
|
10
10
|
thresholds: {
|
|
11
11
|
tier: number;
|
|
12
|
-
|
|
13
|
-
wallet_stop: number;
|
|
12
|
+
wallet: number;
|
|
14
13
|
};
|
|
15
14
|
fallbacks: {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
15
|
+
free: {
|
|
16
|
+
main: string;
|
|
17
|
+
agent: string;
|
|
18
|
+
};
|
|
19
|
+
enter: {
|
|
20
|
+
agent: string;
|
|
21
|
+
};
|
|
22
22
|
};
|
|
23
23
|
enablePaidTools: boolean;
|
|
24
|
+
costThreshold: number;
|
|
25
|
+
costConfirmationRequired: boolean;
|
|
24
26
|
statusBar: boolean;
|
|
27
|
+
costEstimator: boolean;
|
|
25
28
|
}
|
|
26
|
-
export declare function loadConfig():
|
|
27
|
-
export declare function saveConfig(updates: Partial<
|
|
29
|
+
export declare function loadConfig(): PollinationsConfigV5;
|
|
30
|
+
export declare function saveConfig(updates: Partial<PollinationsConfigV5>): {
|
|
28
31
|
version: string;
|
|
29
|
-
mode: "manual" | "
|
|
32
|
+
mode: "manual" | "alwaysfree" | "pro";
|
|
30
33
|
apiKey?: string;
|
|
31
34
|
keyHasAccessToProfile?: boolean;
|
|
32
35
|
gui: {
|
|
@@ -35,19 +38,20 @@ export declare function saveConfig(updates: Partial<PollinationsConfigV6>): {
|
|
|
35
38
|
};
|
|
36
39
|
thresholds: {
|
|
37
40
|
tier: number;
|
|
38
|
-
|
|
39
|
-
wallet_stop: number;
|
|
41
|
+
wallet: number;
|
|
40
42
|
};
|
|
41
43
|
fallbacks: {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
44
|
+
free: {
|
|
45
|
+
main: string;
|
|
46
|
+
agent: string;
|
|
47
|
+
};
|
|
48
|
+
enter: {
|
|
49
|
+
agent: string;
|
|
50
|
+
};
|
|
48
51
|
};
|
|
49
52
|
enablePaidTools: boolean;
|
|
53
|
+
costThreshold: number;
|
|
54
|
+
costConfirmationRequired: boolean;
|
|
50
55
|
statusBar: boolean;
|
|
56
|
+
costEstimator: boolean;
|
|
51
57
|
};
|
|
52
|
-
export declare function initSessionWallet(walletBalance: number): void;
|
|
53
|
-
export declare function getWalletWarnPercent(): number;
|
package/dist/server/config.js
CHANGED
|
@@ -9,7 +9,7 @@ const CONFIG_DIR_OPENCODE = path.join(HOMEDIR, '.config', 'opencode');
|
|
|
9
9
|
const OPENCODE_CONFIG_FILE = path.join(CONFIG_DIR_OPENCODE, 'opencode.json');
|
|
10
10
|
const AUTH_FILE = path.join(HOMEDIR, '.local', 'share', 'opencode', 'auth.json');
|
|
11
11
|
// LOAD PACKAGE VERSION
|
|
12
|
-
let PKG_VERSION = '
|
|
12
|
+
let PKG_VERSION = '5.2.0';
|
|
13
13
|
try {
|
|
14
14
|
const pkgPath = path.join(__dirname, '../../package.json');
|
|
15
15
|
if (fs.existsSync(pkgPath)) {
|
|
@@ -18,23 +18,21 @@ try {
|
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
catch (e) { }
|
|
21
|
-
const
|
|
21
|
+
const DEFAULT_CONFIG_V5 = {
|
|
22
22
|
version: PKG_VERSION,
|
|
23
|
-
mode: '
|
|
23
|
+
mode: 'manual',
|
|
24
24
|
gui: { status: 'alert', logs: 'none' },
|
|
25
|
-
thresholds: {
|
|
26
|
-
tier: 20, // 20% tier restant → alerte/fallback
|
|
27
|
-
wallet_warn: 20, // 20% wallet restant → alerte (pro)
|
|
28
|
-
wallet_stop: 0.50 // $0.50 → stop absolu (pro)
|
|
29
|
-
},
|
|
25
|
+
thresholds: { tier: 10, wallet: 5 },
|
|
30
26
|
fallbacks: {
|
|
31
|
-
|
|
32
|
-
|
|
27
|
+
free: { main: 'free/mistral', agent: 'free/openai-fast' },
|
|
28
|
+
enter: { agent: 'free/openai-fast' }
|
|
33
29
|
},
|
|
34
|
-
session: {},
|
|
35
30
|
enablePaidTools: false,
|
|
36
|
-
|
|
37
|
-
|
|
31
|
+
costThreshold: 0.15, // Default 0.15 🌻
|
|
32
|
+
costConfirmationRequired: true, // Ask confirmation when cost exceeds threshold
|
|
33
|
+
keyHasAccessToProfile: true, // Default true for legacy keys
|
|
34
|
+
statusBar: true,
|
|
35
|
+
costEstimator: true, // Show cost estimates by default
|
|
38
36
|
};
|
|
39
37
|
function logConfig(msg) {
|
|
40
38
|
try {
|
|
@@ -45,28 +43,17 @@ function logConfig(msg) {
|
|
|
45
43
|
}
|
|
46
44
|
catch (e) { }
|
|
47
45
|
}
|
|
48
|
-
// MIGRATION: alwaysfree → economy
|
|
49
|
-
function migrateConfig(config) {
|
|
50
|
-
if (config.mode === 'alwaysfree') {
|
|
51
|
-
config.mode = 'economy';
|
|
52
|
-
logConfig('[Migration] alwaysfree → economy');
|
|
53
|
-
}
|
|
54
|
-
// Migrate old fallbacks structure
|
|
55
|
-
if (config.fallbacks?.free?.main) {
|
|
56
|
-
config.fallbacks.economy = config.fallbacks.free.main.replace('free/', '');
|
|
57
|
-
delete config.fallbacks.free;
|
|
58
|
-
logConfig('[Migration] fallbacks.free → fallbacks.economy');
|
|
59
|
-
}
|
|
60
|
-
return config;
|
|
61
|
-
}
|
|
62
46
|
// SIMPLE LOAD (Direct Disk Read - No Caching, No Watchers)
|
|
47
|
+
// This ensures the Proxy ALWAYS sees the latest state from auth.json
|
|
63
48
|
export function loadConfig() {
|
|
64
49
|
return readConfigFromDisk();
|
|
65
50
|
}
|
|
66
51
|
function readConfigFromDisk() {
|
|
67
|
-
let config = { ...
|
|
52
|
+
let config = { ...DEFAULT_CONFIG_V5 };
|
|
68
53
|
let finalKey = undefined;
|
|
69
54
|
let source = 'none';
|
|
55
|
+
// TIMESTAMP BASED PRIORITY LOGIC
|
|
56
|
+
// We want the most recently updated Valid Key to win.
|
|
70
57
|
let configTime = 0;
|
|
71
58
|
let authTime = 0;
|
|
72
59
|
try {
|
|
@@ -85,7 +72,7 @@ function readConfigFromDisk() {
|
|
|
85
72
|
try {
|
|
86
73
|
const raw = fs.readFileSync(CONFIG_FILE, 'utf-8');
|
|
87
74
|
const custom = JSON.parse(raw);
|
|
88
|
-
config = { ...config, ...
|
|
75
|
+
config = { ...config, ...custom }; // Helper: We load the rest of config anyway
|
|
89
76
|
if (custom.apiKey && custom.apiKey.length > 5)
|
|
90
77
|
configKey = custom.apiKey;
|
|
91
78
|
}
|
|
@@ -106,6 +93,7 @@ function readConfigFromDisk() {
|
|
|
106
93
|
catch (e) { }
|
|
107
94
|
}
|
|
108
95
|
// 2. DETERMINE WINNER
|
|
96
|
+
// If both exist, newest wins. If one exists, it wins.
|
|
109
97
|
if (configKey && authKey) {
|
|
110
98
|
if (configTime >= authTime) {
|
|
111
99
|
finalKey = configKey;
|
|
@@ -143,9 +131,16 @@ function readConfigFromDisk() {
|
|
|
143
131
|
// 4. APPLY
|
|
144
132
|
if (finalKey) {
|
|
145
133
|
config.apiKey = finalKey;
|
|
134
|
+
// config.mode = 'pro'; // REMOVED: Mode is decoupled from Key presence.
|
|
146
135
|
}
|
|
147
136
|
else {
|
|
137
|
+
// Ensure no phantom key remains
|
|
148
138
|
delete config.apiKey;
|
|
139
|
+
// if (config.mode === 'pro') config.mode = 'manual'; // OPTIONAL: Downgrade if no key? User says "No link".
|
|
140
|
+
// Actually, if I am in PRO mode and lose my key, I am broken. Falling back to manual is safer?
|
|
141
|
+
// User said "Manual mode is like standard API".
|
|
142
|
+
// Let's REMOVE this auto-downgrade too to be strictly "Decoupled".
|
|
143
|
+
// If user is in PRO without key, they get "Missing Key" error, which is correct.
|
|
149
144
|
}
|
|
150
145
|
return { ...config, version: PKG_VERSION };
|
|
151
146
|
}
|
|
@@ -157,7 +152,6 @@ export function saveConfig(updates) {
|
|
|
157
152
|
fs.mkdirSync(CONFIG_DIR_POLLI, { recursive: true });
|
|
158
153
|
}
|
|
159
154
|
fs.writeFileSync(CONFIG_FILE, JSON.stringify(updated, null, 2));
|
|
160
|
-
logConfig(`[SaveConfig] Updated: ${Object.keys(updates).join(', ')}`);
|
|
161
155
|
return updated;
|
|
162
156
|
}
|
|
163
157
|
catch (e) {
|
|
@@ -165,23 +159,3 @@ export function saveConfig(updates) {
|
|
|
165
159
|
throw e;
|
|
166
160
|
}
|
|
167
161
|
}
|
|
168
|
-
// SESSION WALLET TRACKING
|
|
169
|
-
export function initSessionWallet(walletBalance) {
|
|
170
|
-
const config = loadConfig();
|
|
171
|
-
if (!config.session.wallet_initial) {
|
|
172
|
-
saveConfig({
|
|
173
|
-
session: {
|
|
174
|
-
wallet_initial: walletBalance,
|
|
175
|
-
session_start: new Date().toISOString()
|
|
176
|
-
}
|
|
177
|
-
});
|
|
178
|
-
logConfig(`[Session] Wallet initial stocké: $${walletBalance}`);
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
export function getWalletWarnPercent() {
|
|
182
|
-
const config = loadConfig();
|
|
183
|
-
const initial = config.session.wallet_initial;
|
|
184
|
-
if (!initial || initial <= 0)
|
|
185
|
-
return 100; // No reference = no warning
|
|
186
|
-
return config.thresholds.wallet_warn;
|
|
187
|
-
}
|
|
@@ -1,34 +1,8 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* generate-config.ts - v6.0 Simplified
|
|
3
|
-
*
|
|
4
|
-
* Single endpoint: gen.pollinations.ai/text/models
|
|
5
|
-
* No more Free tier, no cache ETag, no prefixes
|
|
6
|
-
*/
|
|
7
|
-
export interface PollinationsModel {
|
|
8
|
-
name: string;
|
|
9
|
-
description?: string;
|
|
10
|
-
type?: string;
|
|
11
|
-
tools?: boolean;
|
|
12
|
-
reasoning?: boolean;
|
|
13
|
-
context?: number;
|
|
14
|
-
context_window?: number;
|
|
15
|
-
input_modalities?: string[];
|
|
16
|
-
output_modalities?: string[];
|
|
17
|
-
paid_only?: boolean;
|
|
18
|
-
vision?: boolean;
|
|
19
|
-
audio?: boolean;
|
|
20
|
-
pricing?: {
|
|
21
|
-
promptTextTokens?: number;
|
|
22
|
-
completionTextTokens?: number;
|
|
23
|
-
promptImageTokens?: number;
|
|
24
|
-
promptAudioTokens?: number;
|
|
25
|
-
completionAudioTokens?: number;
|
|
26
|
-
};
|
|
27
|
-
[key: string]: any;
|
|
28
|
-
}
|
|
29
1
|
interface OpenCodeModel {
|
|
30
2
|
id: string;
|
|
31
3
|
name: string;
|
|
4
|
+
object: string;
|
|
5
|
+
variants?: any;
|
|
32
6
|
options?: any;
|
|
33
7
|
limit?: {
|
|
34
8
|
context?: number;
|
|
@@ -38,7 +12,6 @@ interface OpenCodeModel {
|
|
|
38
12
|
input?: string[];
|
|
39
13
|
output?: string[];
|
|
40
14
|
};
|
|
41
|
-
tool_call?: boolean;
|
|
42
15
|
}
|
|
43
|
-
export declare function generatePollinationsConfig(forceApiKey?: string): Promise<OpenCodeModel[]>;
|
|
16
|
+
export declare function generatePollinationsConfig(forceApiKey?: string, forceStrict?: boolean): Promise<OpenCodeModel[]>;
|
|
44
17
|
export {};
|