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.
Files changed (56) hide show
  1. package/README.md +140 -87
  2. package/dist/index.js +33 -154
  3. package/dist/server/commands.d.ts +2 -0
  4. package/dist/server/commands.js +106 -60
  5. package/dist/server/config.d.ts +27 -23
  6. package/dist/server/config.js +24 -50
  7. package/dist/server/generate-config.d.ts +3 -30
  8. package/dist/server/generate-config.js +172 -100
  9. package/dist/server/index.d.ts +2 -1
  10. package/dist/server/index.js +124 -149
  11. package/dist/server/pollinations-api.d.ts +11 -0
  12. package/dist/server/pollinations-api.js +20 -0
  13. package/dist/server/proxy.js +187 -149
  14. package/dist/server/quota.d.ts +8 -0
  15. package/dist/server/quota.js +106 -61
  16. package/dist/server/toast.d.ts +3 -0
  17. package/dist/server/toast.js +16 -0
  18. package/dist/tools/design/gen_diagram.d.ts +2 -0
  19. package/dist/tools/design/gen_diagram.js +94 -0
  20. package/dist/tools/design/gen_palette.d.ts +2 -0
  21. package/dist/tools/design/gen_palette.js +182 -0
  22. package/dist/tools/design/gen_qrcode.d.ts +2 -0
  23. package/dist/tools/design/gen_qrcode.js +50 -0
  24. package/dist/tools/index.d.ts +22 -0
  25. package/dist/tools/index.js +81 -0
  26. package/dist/tools/pollinations/deepsearch.d.ts +7 -0
  27. package/dist/tools/pollinations/deepsearch.js +80 -0
  28. package/dist/tools/pollinations/gen_audio.d.ts +18 -0
  29. package/dist/tools/pollinations/gen_audio.js +204 -0
  30. package/dist/tools/pollinations/gen_image.d.ts +13 -0
  31. package/dist/tools/pollinations/gen_image.js +239 -0
  32. package/dist/tools/pollinations/gen_music.d.ts +14 -0
  33. package/dist/tools/pollinations/gen_music.js +139 -0
  34. package/dist/tools/pollinations/gen_video.d.ts +16 -0
  35. package/dist/tools/pollinations/gen_video.js +222 -0
  36. package/dist/tools/pollinations/search_crawl_scrape.d.ts +7 -0
  37. package/dist/tools/pollinations/search_crawl_scrape.js +85 -0
  38. package/dist/tools/pollinations/shared.d.ts +170 -0
  39. package/dist/tools/pollinations/shared.js +454 -0
  40. package/dist/tools/pollinations/transcribe_audio.d.ts +17 -0
  41. package/dist/tools/pollinations/transcribe_audio.js +235 -0
  42. package/dist/tools/power/extract_audio.d.ts +2 -0
  43. package/dist/tools/power/extract_audio.js +180 -0
  44. package/dist/tools/power/extract_frames.d.ts +2 -0
  45. package/dist/tools/power/extract_frames.js +240 -0
  46. package/dist/tools/power/file_to_url.d.ts +2 -0
  47. package/dist/tools/power/file_to_url.js +217 -0
  48. package/dist/tools/power/remove_background.d.ts +2 -0
  49. package/dist/tools/power/remove_background.js +365 -0
  50. package/dist/tools/power/rmbg_keys.d.ts +2 -0
  51. package/dist/tools/power/rmbg_keys.js +78 -0
  52. package/dist/tools/shared.d.ts +30 -0
  53. package/dist/tools/shared.js +74 -0
  54. package/package.json +9 -3
  55. package/dist/server/models-seed.d.ts +0 -18
  56. package/dist/server/models-seed.js +0 -55
@@ -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 economy or manual, or verified pro)
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 [mode, model] = args;
268
- if (!mode) {
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- Economy: ${config.fallbacks.economy}\n- Pro: ${config.fallbacks.pro}`
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
- if (mode === 'economy' && model) {
277
- saveConfig({
278
- fallbacks: { ...config.fallbacks, economy: model }
279
- });
280
- return {
281
- handled: true,
282
- response: `✅ Fallback Economy configuré: ${model}`
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
- error: `Usage: /pollinations fallback [economy|pro] <modèle>`
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 real models (not just connect placeholder)
312
- const realModels = models.filter(m => m.id !== 'connect');
313
- if (realModels.length > 0) {
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 = realModels.filter(m => m.name.includes('💎')).length;
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! (${realModels.length} modèles débloqués)`, 'Pollinations Config');
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: ${realModels.length} (dont ${diamondCount} 💎 Paid)${forcedModeMsg}`
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
- // v6.0: No fallback prefix check needed. If models is empty (only connect), key is invalid.
359
- throw new Error("Aucun modèle détecté pour cette clé. Clé invalide ou expirée.");
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 === 'threshold_wallet_warn' && value) {
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, wallet_warn: threshold } });
425
- return { handled: true, response: `✅ threshold_wallet_warn = ${threshold}%` };
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, threshold_wallet_warn, threshold_wallet_stop, status_bar`
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 V5
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 (Free).
468
+ - **\`/pollinations fallback <main> [agent]\`**: Configure le Safety Net.
469
+
470
+ **Configuration**
453
471
  - **\`/pollinations config [key] [value]\`**:
454
- - \`status_gui\`: none, alert, all (Status Dashboard).
455
- - \`logs_gui\`: none, error, verbose (Logs Techniques).
456
- - \`threshold_tier\`: 0-100 (Alerte %).
457
- - \`threshold_wallet\`: 0-100 (Safety Net %).
458
- - \`status_bar\`: true/false (Widget).
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
- const result = await handleCommand(input.command);
467
- if (result.handled) {
468
- output.handled = true;
469
- if (result.response) {
470
- output.response = result.response;
471
- }
472
- if (result.error) {
473
- output.error = result.error;
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
  }
@@ -1,6 +1,6 @@
1
- export interface PollinationsConfigV6 {
1
+ export interface PollinationsConfigV5 {
2
2
  version: string | number;
3
- mode: 'manual' | 'economy' | 'pro';
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
- wallet_warn: number;
13
- wallet_stop: number;
12
+ wallet: number;
14
13
  };
15
14
  fallbacks: {
16
- economy: string;
17
- pro: string;
18
- };
19
- session: {
20
- wallet_initial?: number;
21
- session_start?: string;
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(): PollinationsConfigV6;
27
- export declare function saveConfig(updates: Partial<PollinationsConfigV6>): {
29
+ export declare function loadConfig(): PollinationsConfigV5;
30
+ export declare function saveConfig(updates: Partial<PollinationsConfigV5>): {
28
31
  version: string;
29
- mode: "manual" | "economy" | "pro";
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
- wallet_warn: number;
39
- wallet_stop: number;
41
+ wallet: number;
40
42
  };
41
43
  fallbacks: {
42
- economy: string;
43
- pro: string;
44
- };
45
- session: {
46
- wallet_initial?: number;
47
- session_start?: string;
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;
@@ -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 = '6.1.0';
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 DEFAULT_CONFIG_V6 = {
21
+ const DEFAULT_CONFIG_V5 = {
22
22
  version: PKG_VERSION,
23
- mode: 'economy', // Défaut: economy (protège le wallet)
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
- economy: 'nova-fast',
32
- pro: 'qwen-coder'
27
+ free: { main: 'free/mistral', agent: 'free/openai-fast' },
28
+ enter: { agent: 'free/openai-fast' }
33
29
  },
34
- session: {},
35
30
  enablePaidTools: false,
36
- keyHasAccessToProfile: true,
37
- statusBar: true
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 = { ...DEFAULT_CONFIG_V6 };
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, ...migrateConfig(custom) };
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 {};