opencode-pollinations-plugin 6.1.0-beta.2 → 6.1.0-beta.22

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 (96) hide show
  1. package/README.md +242 -62
  2. package/dist/index.js +68 -159
  3. package/dist/server/commands.d.ts +6 -0
  4. package/dist/server/commands.js +400 -71
  5. package/dist/server/config.d.ts +32 -23
  6. package/dist/server/config.js +183 -99
  7. package/dist/server/connect-response.d.ts +2 -0
  8. package/dist/server/connect-response.js +141 -0
  9. package/dist/server/generate-config.d.ts +3 -30
  10. package/dist/server/generate-config.js +164 -106
  11. package/dist/server/index.d.ts +2 -1
  12. package/dist/server/index.js +124 -149
  13. package/dist/server/logger.d.ts +8 -0
  14. package/dist/server/logger.js +36 -0
  15. package/dist/server/models/cache.d.ts +35 -0
  16. package/dist/server/models/cache.js +160 -0
  17. package/dist/server/models/fetcher.d.ts +18 -0
  18. package/dist/server/models/fetcher.js +150 -0
  19. package/dist/server/models/index.d.ts +6 -0
  20. package/dist/server/models/index.js +5 -0
  21. package/dist/server/models/manual.d.ts +15 -0
  22. package/dist/server/models/manual.js +92 -0
  23. package/dist/server/models/types.d.ts +55 -0
  24. package/dist/server/models/types.js +7 -0
  25. package/dist/server/models/worker.d.ts +21 -0
  26. package/dist/server/models/worker.js +97 -0
  27. package/dist/server/pollinations-api.d.ts +11 -0
  28. package/dist/server/pollinations-api.js +21 -8
  29. package/dist/server/proxy.js +223 -160
  30. package/dist/server/quota.d.ts +2 -0
  31. package/dist/server/quota.js +89 -86
  32. package/dist/server/scripts/pollinations_pricing.d.ts +8 -0
  33. package/dist/server/scripts/pollinations_pricing.js +246 -0
  34. package/dist/server/scripts/test_cost_endpoints.d.ts +1 -0
  35. package/dist/server/scripts/test_cost_endpoints.js +61 -0
  36. package/dist/server/scripts/test_dynamic_pricing.d.ts +1 -0
  37. package/dist/server/scripts/test_dynamic_pricing.js +39 -0
  38. package/dist/server/scripts/test_freetier_audit.d.ts +11 -0
  39. package/dist/server/scripts/test_freetier_audit.js +215 -0
  40. package/dist/server/scripts/test_parallel_cost.d.ts +1 -0
  41. package/dist/server/scripts/test_parallel_cost.js +104 -0
  42. package/dist/server/toast.d.ts +7 -1
  43. package/dist/server/toast.js +43 -10
  44. package/dist/tools/design/gen_diagram.d.ts +2 -0
  45. package/dist/tools/design/gen_diagram.js +94 -0
  46. package/dist/tools/design/gen_palette.d.ts +2 -0
  47. package/dist/tools/design/gen_palette.js +182 -0
  48. package/dist/tools/design/gen_qrcode.d.ts +2 -0
  49. package/dist/tools/design/gen_qrcode.js +50 -0
  50. package/dist/tools/ffmpeg.d.ts +24 -0
  51. package/dist/tools/ffmpeg.js +54 -0
  52. package/dist/tools/index.d.ts +24 -0
  53. package/dist/tools/index.js +83 -0
  54. package/dist/tools/pollinations/beta_discovery.d.ts +9 -0
  55. package/dist/tools/pollinations/beta_discovery.js +197 -0
  56. package/dist/tools/pollinations/cost-guard.d.ts +38 -0
  57. package/dist/tools/pollinations/cost-guard.js +141 -0
  58. package/dist/tools/pollinations/deepsearch.d.ts +7 -0
  59. package/dist/tools/pollinations/deepsearch.js +80 -0
  60. package/dist/tools/pollinations/gen_audio.d.ts +18 -0
  61. package/dist/tools/pollinations/gen_audio.js +246 -0
  62. package/dist/tools/pollinations/gen_image.d.ts +11 -0
  63. package/dist/tools/pollinations/gen_image.js +225 -0
  64. package/dist/tools/pollinations/gen_music.d.ts +14 -0
  65. package/dist/tools/pollinations/gen_music.js +180 -0
  66. package/dist/tools/pollinations/gen_video.d.ts +16 -0
  67. package/dist/tools/pollinations/gen_video.js +256 -0
  68. package/dist/tools/pollinations/polli_gen_confirm.d.ts +2 -0
  69. package/dist/tools/pollinations/polli_gen_confirm.js +48 -0
  70. package/dist/tools/pollinations/polli_status.d.ts +2 -0
  71. package/dist/tools/pollinations/polli_status.js +31 -0
  72. package/dist/tools/pollinations/polli_web_search.d.ts +15 -0
  73. package/dist/tools/pollinations/polli_web_search.js +164 -0
  74. package/dist/tools/pollinations/search_crawl_scrape.d.ts +7 -0
  75. package/dist/tools/pollinations/search_crawl_scrape.js +85 -0
  76. package/dist/tools/pollinations/shared.d.ts +165 -0
  77. package/dist/tools/pollinations/shared.js +665 -0
  78. package/dist/tools/pollinations/test_estimators.d.ts +1 -0
  79. package/dist/tools/pollinations/test_estimators.js +22 -0
  80. package/dist/tools/pollinations/transcribe_audio.d.ts +13 -0
  81. package/dist/tools/pollinations/transcribe_audio.js +194 -0
  82. package/dist/tools/power/extract_audio.d.ts +2 -0
  83. package/dist/tools/power/extract_audio.js +179 -0
  84. package/dist/tools/power/extract_frames.d.ts +2 -0
  85. package/dist/tools/power/extract_frames.js +237 -0
  86. package/dist/tools/power/file_to_url.d.ts +2 -0
  87. package/dist/tools/power/file_to_url.js +217 -0
  88. package/dist/tools/power/remove_background.d.ts +2 -0
  89. package/dist/tools/power/remove_background.js +366 -0
  90. package/dist/tools/power/rmbg_keys.d.ts +2 -0
  91. package/dist/tools/power/rmbg_keys.js +79 -0
  92. package/dist/tools/shared.d.ts +30 -0
  93. package/dist/tools/shared.js +80 -0
  94. package/package.json +10 -4
  95. package/dist/server/models-seed.d.ts +0 -18
  96. package/dist/server/models-seed.js +0 -55
@@ -1,6 +1,9 @@
1
- export interface PollinationsConfigV6 {
1
+ export declare function getConfigDir(): string;
2
+ export declare const CONFIG_DIR: string;
3
+ export declare const CONFIG_FILE: string;
4
+ export interface PollinationsConfigV5 {
2
5
  version: string | number;
3
- mode: 'manual' | 'economy' | 'pro';
6
+ mode: 'manual' | 'alwaysfree' | 'pro';
4
7
  apiKey?: string;
5
8
  keyHasAccessToProfile?: boolean;
6
9
  gui: {
@@ -9,24 +12,27 @@ export interface PollinationsConfigV6 {
9
12
  };
10
13
  thresholds: {
11
14
  tier: number;
12
- wallet_warn: number;
13
- wallet_stop: number;
15
+ wallet: number;
14
16
  };
15
17
  fallbacks: {
16
- economy: string;
17
- pro: string;
18
- };
19
- session: {
20
- wallet_initial?: number;
21
- session_start?: string;
18
+ free: {
19
+ main: string;
20
+ agent: string;
21
+ };
22
+ enter: {
23
+ agent: string;
24
+ };
22
25
  };
23
26
  enablePaidTools: boolean;
27
+ costThreshold: number;
28
+ costConfirmationRequired: boolean;
24
29
  statusBar: boolean;
30
+ costEstimator: boolean;
25
31
  }
26
- export declare function loadConfig(): PollinationsConfigV6;
27
- export declare function saveConfig(updates: Partial<PollinationsConfigV6>): {
32
+ export declare function loadConfig(): PollinationsConfigV5;
33
+ export declare function saveConfig(updates: Partial<PollinationsConfigV5>): {
28
34
  version: string;
29
- mode: "manual" | "economy" | "pro";
35
+ mode: "manual" | "alwaysfree" | "pro";
30
36
  apiKey?: string;
31
37
  keyHasAccessToProfile?: boolean;
32
38
  gui: {
@@ -35,19 +41,22 @@ export declare function saveConfig(updates: Partial<PollinationsConfigV6>): {
35
41
  };
36
42
  thresholds: {
37
43
  tier: number;
38
- wallet_warn: number;
39
- wallet_stop: number;
44
+ wallet: number;
40
45
  };
41
46
  fallbacks: {
42
- economy: string;
43
- pro: string;
44
- };
45
- session: {
46
- wallet_initial?: number;
47
- session_start?: string;
47
+ free: {
48
+ main: string;
49
+ agent: string;
50
+ };
51
+ enter: {
52
+ agent: string;
53
+ };
48
54
  };
49
55
  enablePaidTools: boolean;
56
+ costThreshold: number;
57
+ costConfirmationRequired: boolean;
50
58
  statusBar: boolean;
59
+ costEstimator: boolean;
51
60
  };
52
- export declare function initSessionWallet(walletBalance: number): void;
53
- export declare function getWalletWarnPercent(): number;
61
+ export declare function saveKeyToAuthJson(key: string): boolean;
62
+ export declare function migrateLegacyConfig(): void;
@@ -2,14 +2,61 @@ import * as fs from 'fs';
2
2
  import * as path from 'path';
3
3
  import * as os from 'os';
4
4
  // PATHS
5
+ // PATHS & CROSS-PLATFORM LOGIC
6
+ export function getConfigDir() {
7
+ switch (process.platform) {
8
+ case 'win32':
9
+ return path.join(process.env.APPDATA || os.homedir(), 'pollinations');
10
+ case 'darwin':
11
+ return path.join(os.homedir(), 'Library', 'Application Support', 'pollinations');
12
+ default:
13
+ return path.join(process.env.XDG_CONFIG_HOME || path.join(os.homedir(), '.config'), 'pollinations');
14
+ }
15
+ }
16
+ export const CONFIG_DIR = getConfigDir();
17
+ export const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
18
+ // Legacy/External Paths (OpenCode specific)
5
19
  const HOMEDIR = os.homedir();
6
- const CONFIG_DIR_POLLI = path.join(HOMEDIR, '.pollinations');
7
- const CONFIG_FILE = path.join(CONFIG_DIR_POLLI, 'config.json');
8
- const CONFIG_DIR_OPENCODE = path.join(HOMEDIR, '.config', 'opencode');
9
- const OPENCODE_CONFIG_FILE = path.join(CONFIG_DIR_OPENCODE, 'opencode.json');
10
- const AUTH_FILE = path.join(HOMEDIR, '.local', 'share', 'opencode', 'auth.json');
20
+ // Multi-OS Candidate Paths for Auth & Global Config
21
+ function getExternalConfigPaths() {
22
+ const candidatesAuth = [];
23
+ const candidatesConfig = [];
24
+ // 0. OpenCode Environment Variables (Highest Priority)
25
+ if (process.env.OPENCODE_CONFIG) {
26
+ // Direct config file path
27
+ candidatesConfig.push(process.env.OPENCODE_CONFIG);
28
+ }
29
+ if (process.env.OPENCODE_CONFIG_DIR) {
30
+ // Config directory override
31
+ candidatesConfig.push(path.join(process.env.OPENCODE_CONFIG_DIR, 'opencode.json'));
32
+ candidatesConfig.push(path.join(process.env.OPENCODE_CONFIG_DIR, 'config.json'));
33
+ candidatesAuth.push(path.join(process.env.OPENCODE_CONFIG_DIR, 'auth.json'));
34
+ }
35
+ // Also check standard env vars often used in overrides
36
+ if (process.env.OPENCODE_AUTH)
37
+ candidatesAuth.push(process.env.OPENCODE_AUTH);
38
+ // 1. Linux Standard (Current)
39
+ // ... rest of function ...
40
+ candidatesAuth.push(path.join(HOMEDIR, '.local', 'share', 'opencode', 'auth.json'));
41
+ candidatesConfig.push(path.join(HOMEDIR, '.config', 'opencode', 'opencode.json'));
42
+ // 2. Windows Standard (%APPDATA%)
43
+ if (process.platform === 'win32') {
44
+ const appData = process.env.APPDATA || path.join(HOMEDIR, 'AppData', 'Roaming');
45
+ candidatesAuth.push(path.join(appData, 'opencode', 'auth.json'));
46
+ candidatesAuth.push(path.join(appData, 'OpenCode', 'auth.json'));
47
+ candidatesConfig.push(path.join(appData, 'opencode', 'config.json'));
48
+ }
49
+ // 3. Mac Standard
50
+ if (process.platform === 'darwin') {
51
+ const support = path.join(HOMEDIR, 'Library', 'Application Support', 'OpenCode');
52
+ candidatesAuth.push(path.join(support, 'auth.json'));
53
+ candidatesConfig.push(path.join(support, 'config.json'));
54
+ }
55
+ return { auth: candidatesAuth, config: candidatesConfig };
56
+ }
57
+ const EXTERNAL_PATHS = getExternalConfigPaths();
11
58
  // LOAD PACKAGE VERSION
12
- let PKG_VERSION = '6.1.0';
59
+ let PKG_VERSION = '5.2.0';
13
60
  try {
14
61
  const pkgPath = path.join(__dirname, '../../package.json');
15
62
  if (fs.existsSync(pkgPath)) {
@@ -18,65 +65,37 @@ try {
18
65
  }
19
66
  }
20
67
  catch (e) { }
21
- const DEFAULT_CONFIG_V6 = {
68
+ const DEFAULT_CONFIG_V5 = {
22
69
  version: PKG_VERSION,
23
- mode: 'economy', // Défaut: economy (protège le wallet)
70
+ mode: 'manual',
24
71
  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
- },
72
+ thresholds: { tier: 10, wallet: 5 },
30
73
  fallbacks: {
31
- economy: 'nova-fast',
32
- pro: 'qwen-coder'
74
+ free: { main: 'free/mistral', agent: 'free/openai-fast' },
75
+ enter: { agent: 'free/openai-fast' }
33
76
  },
34
- session: {},
35
77
  enablePaidTools: false,
36
- keyHasAccessToProfile: true,
37
- statusBar: true
78
+ costThreshold: 0.15, // Default 0.15 🌻
79
+ costConfirmationRequired: true, // Ask confirmation when cost exceeds threshold
80
+ keyHasAccessToProfile: true, // Default true for legacy keys
81
+ statusBar: true,
82
+ costEstimator: true, // Show cost estimates by default
38
83
  };
84
+ import { log as logSystem } from './logger.js';
39
85
  function logConfig(msg) {
40
- try {
41
- if (!fs.existsSync('/tmp/opencode_pollinations_config_debug.log')) {
42
- fs.writeFileSync('/tmp/opencode_pollinations_config_debug.log', '');
43
- }
44
- fs.appendFileSync('/tmp/opencode_pollinations_config_debug.log', `[${new Date().toISOString()}] ${msg}\n`);
45
- }
46
- catch (e) { }
47
- }
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
- if (!config.fallbacks)
57
- config.fallbacks = {};
58
- config.fallbacks.economy = config.fallbacks.free.main.replace('free/', '');
59
- delete config.fallbacks.free;
60
- logConfig('[Migration] fallbacks.free → fallbacks.economy');
61
- }
62
- // Migrate old wallet threshold
63
- if (config.thresholds?.wallet) {
64
- if (!config.thresholds.wallet_warn) {
65
- config.thresholds.wallet_warn = config.thresholds.wallet;
66
- }
67
- delete config.thresholds.wallet;
68
- logConfig('[Migration] thresholds.wallet → thresholds.wallet_warn');
69
- }
70
- return config;
86
+ logSystem(`[Config] ${msg}`);
71
87
  }
72
88
  // SIMPLE LOAD (Direct Disk Read - No Caching, No Watchers)
89
+ // This ensures the Proxy ALWAYS sees the latest state from auth.json
73
90
  export function loadConfig() {
74
91
  return readConfigFromDisk();
75
92
  }
76
93
  function readConfigFromDisk() {
77
- let config = { ...DEFAULT_CONFIG_V6 };
94
+ let config = { ...DEFAULT_CONFIG_V5 };
78
95
  let finalKey = undefined;
79
96
  let source = 'none';
97
+ // TIMESTAMP BASED PRIORITY LOGIC
98
+ // We want the most recently updated Valid Key to win.
80
99
  let configTime = 0;
81
100
  let authTime = 0;
82
101
  try {
@@ -85,45 +104,62 @@ function readConfigFromDisk() {
85
104
  }
86
105
  catch (e) { }
87
106
  try {
88
- if (fs.existsSync(AUTH_FILE))
89
- authTime = fs.statSync(AUTH_FILE).mtime.getTime();
107
+ if (fs.existsSync(CONFIG_FILE))
108
+ configTime = fs.statSync(CONFIG_FILE).mtime.getTime();
109
+ }
110
+ catch (e) { }
111
+ try {
112
+ for (const f of EXTERNAL_PATHS.auth) {
113
+ if (fs.existsSync(f)) {
114
+ authTime = Math.max(authTime, fs.statSync(f).mtime.getTime());
115
+ }
116
+ }
90
117
  }
91
118
  catch (e) { }
92
119
  // 1. EXTRACT KEYS
120
+ // 1. EXTRACT KEYS
93
121
  let configKey = undefined;
94
122
  if (fs.existsSync(CONFIG_FILE)) {
95
123
  try {
96
124
  const raw = fs.readFileSync(CONFIG_FILE, 'utf-8');
97
125
  const custom = JSON.parse(raw);
98
- const migrated = migrateConfig(custom);
99
- // DEEP MERGE for nested objects to preserve defaults vs overrides
100
- config = {
101
- ...config,
102
- ...migrated,
103
- thresholds: { ...config.thresholds, ...(migrated.thresholds || {}) },
104
- fallbacks: { ...config.fallbacks, ...(migrated.fallbacks || {}) },
105
- gui: { ...config.gui, ...(migrated.gui || {}) }
106
- };
126
+ config = { ...config, ...custom }; // Helper: We load the rest of config anyway
107
127
  if (custom.apiKey && custom.apiKey.length > 5)
108
128
  configKey = custom.apiKey;
109
129
  }
110
- catch (e) { }
130
+ catch (e) {
131
+ logConfig(`ERROR reading config.json: ${e}`);
132
+ // Backup corrupt file to avoid overwrite loop
133
+ try {
134
+ fs.copyFileSync(CONFIG_FILE, CONFIG_FILE + '.corrupt');
135
+ }
136
+ catch { }
137
+ }
111
138
  }
112
139
  let authKey = undefined;
113
- if (fs.existsSync(AUTH_FILE)) {
114
- try {
115
- const raw = fs.readFileSync(AUTH_FILE, 'utf-8');
116
- const authData = JSON.parse(raw);
117
- const entry = authData['pollinations'] || authData['pollinations_enter'] || authData['pollinations_api_key'];
118
- if (entry) {
119
- const k = (typeof entry === 'object' && entry.key) ? entry.key : entry;
120
- if (k && typeof k === 'string' && k.length > 10)
121
- authKey = k;
140
+ // Check all auth candidates
141
+ for (const authFile of EXTERNAL_PATHS.auth) {
142
+ if (fs.existsSync(authFile)) {
143
+ try {
144
+ authTime = Math.max(authTime, fs.statSync(authFile).mtime.getTime()); // Track newest
145
+ const raw = fs.readFileSync(authFile, 'utf-8');
146
+ const authData = JSON.parse(raw);
147
+ const entry = authData['pollinations'] || authData['pollinations_enter'] || authData['pollinations_api_key'];
148
+ if (entry) {
149
+ const k = (typeof entry === 'object' && entry.key) ? entry.key : entry;
150
+ if (k && typeof k === 'string' && k.length > 10) {
151
+ authKey = k;
152
+ break; // Found a key, stop looking (priority to first found? or newest? First in list is Linux default so ok)
153
+ }
154
+ }
155
+ }
156
+ catch (e) {
157
+ logConfig(`ERROR reading auth candidate ${authFile}: ${e}`);
122
158
  }
123
159
  }
124
- catch (e) { }
125
160
  }
126
161
  // 2. DETERMINE WINNER
162
+ // If both exist, newest wins. If one exists, it wins.
127
163
  if (configKey && authKey) {
128
164
  if (configTime >= authTime) {
129
165
  finalKey = configKey;
@@ -145,14 +181,17 @@ function readConfigFromDisk() {
145
181
  // 3. Fallback to OpenCode Global Config (Lowest Priority)
146
182
  if (!finalKey) {
147
183
  try {
148
- if (fs.existsSync(OPENCODE_CONFIG_FILE)) {
149
- const raw = fs.readFileSync(OPENCODE_CONFIG_FILE, 'utf-8');
150
- const data = JSON.parse(raw);
151
- const nativeKey = data?.provider?.pollinations?.options?.apiKey ||
152
- data?.provider?.pollinations_enter?.options?.apiKey;
153
- if (nativeKey && nativeKey.length > 5 && nativeKey !== 'dummy') {
154
- finalKey = nativeKey;
155
- source = 'opencode.json';
184
+ for (const configFile of EXTERNAL_PATHS.config) {
185
+ if (fs.existsSync(configFile)) {
186
+ const raw = fs.readFileSync(configFile, 'utf-8');
187
+ const data = JSON.parse(raw);
188
+ const nativeKey = data?.provider?.pollinations?.options?.apiKey ||
189
+ data?.provider?.pollinations_enter?.options?.apiKey;
190
+ if (nativeKey && nativeKey.length > 5 && nativeKey !== 'dummy') {
191
+ finalKey = nativeKey;
192
+ source = 'opencode_global';
193
+ break;
194
+ }
156
195
  }
157
196
  }
158
197
  }
@@ -161,9 +200,16 @@ function readConfigFromDisk() {
161
200
  // 4. APPLY
162
201
  if (finalKey) {
163
202
  config.apiKey = finalKey;
203
+ // config.mode = 'pro'; // REMOVED: Mode is decoupled from Key presence.
164
204
  }
165
205
  else {
206
+ // Ensure no phantom key remains
166
207
  delete config.apiKey;
208
+ // if (config.mode === 'pro') config.mode = 'manual'; // OPTIONAL: Downgrade if no key? User says "No link".
209
+ // Actually, if I am in PRO mode and lose my key, I am broken. Falling back to manual is safer?
210
+ // User said "Manual mode is like standard API".
211
+ // Let's REMOVE this auto-downgrade too to be strictly "Decoupled".
212
+ // If user is in PRO without key, they get "Missing Key" error, which is correct.
167
213
  }
168
214
  return { ...config, version: PKG_VERSION };
169
215
  }
@@ -171,11 +217,10 @@ export function saveConfig(updates) {
171
217
  try {
172
218
  const current = readConfigFromDisk();
173
219
  const updated = { ...current, ...updates, version: PKG_VERSION };
174
- if (!fs.existsSync(CONFIG_DIR_POLLI)) {
175
- fs.mkdirSync(CONFIG_DIR_POLLI, { recursive: true });
220
+ if (!fs.existsSync(CONFIG_DIR)) {
221
+ fs.mkdirSync(CONFIG_DIR, { recursive: true });
176
222
  }
177
223
  fs.writeFileSync(CONFIG_FILE, JSON.stringify(updated, null, 2));
178
- logConfig(`[SaveConfig] Updated: ${Object.keys(updates).join(', ')}`);
179
224
  return updated;
180
225
  }
181
226
  catch (e) {
@@ -183,23 +228,62 @@ export function saveConfig(updates) {
183
228
  throw e;
184
229
  }
185
230
  }
186
- // SESSION WALLET TRACKING
187
- export function initSessionWallet(walletBalance) {
188
- const config = loadConfig();
189
- if (!config.session.wallet_initial) {
190
- saveConfig({
191
- session: {
192
- wallet_initial: walletBalance,
193
- session_start: new Date().toISOString()
231
+ // === NATIVE AUTH SYNC ===
232
+ export function saveKeyToAuthJson(key) {
233
+ let success = false;
234
+ for (const authFile of EXTERNAL_PATHS.auth) {
235
+ try {
236
+ let authData = {};
237
+ if (fs.existsSync(authFile)) {
238
+ authData = JSON.parse(fs.readFileSync(authFile, 'utf-8'));
239
+ }
240
+ else {
241
+ // Ensure directory exists if we create a new auth.json
242
+ fs.mkdirSync(path.dirname(authFile), { recursive: true });
194
243
  }
195
- });
196
- logConfig(`[Session] Wallet initial stocké: $${walletBalance}`);
244
+ // Set the key (OpenCode standard struct)
245
+ authData['pollinations'] = {
246
+ type: "api",
247
+ key: key
248
+ };
249
+ fs.writeFileSync(authFile, JSON.stringify(authData, null, 2), 'utf-8');
250
+ logConfig(`Synchronized API key to native auth file: ${authFile}`);
251
+ success = true;
252
+ // Only write to the first valid one we find/create, or write to all existing?
253
+ // Usually writing to all existing ones is safest to avoid desync
254
+ }
255
+ catch (e) {
256
+ logConfig(`Failed to sync to auth file ${authFile}: ${e}`);
257
+ }
197
258
  }
259
+ return success;
198
260
  }
199
- export function getWalletWarnPercent() {
200
- const config = loadConfig();
201
- const initial = config.session.wallet_initial;
202
- if (!initial || initial <= 0)
203
- return 100; // No reference = no warning
204
- return config.thresholds.wallet_warn;
261
+ // === MIGRATION UTIL ===
262
+ export function migrateLegacyConfig() {
263
+ try {
264
+ const legacyDir = path.join(os.homedir(), '.pollinations');
265
+ const newDir = getConfigDir();
266
+ if (fs.existsSync(legacyDir) && legacyDir !== newDir) {
267
+ logConfig(`Migrating legacy config from ${legacyDir} to ${newDir}`);
268
+ if (!fs.existsSync(newDir))
269
+ fs.mkdirSync(newDir, { recursive: true });
270
+ const files = fs.readdirSync(legacyDir);
271
+ for (const file of files) {
272
+ const srcPath = path.join(legacyDir, file);
273
+ const destPath = path.join(newDir, file);
274
+ // Don't overwrite existing new files (priority to new system)
275
+ if (!fs.existsSync(destPath)) {
276
+ // Check if it's a file
277
+ if (fs.statSync(srcPath).isFile()) {
278
+ fs.copyFileSync(srcPath, destPath); // Copy first
279
+ // fs.unlinkSync(srcPath); // Optional: Delete old? Let's keep for safety for now.
280
+ logConfig(`Migrated: ${file}`);
281
+ }
282
+ }
283
+ }
284
+ }
285
+ }
286
+ catch (e) {
287
+ logConfig(`Migration Error: ${e}`);
288
+ }
205
289
  }
@@ -0,0 +1,2 @@
1
+ import { PollinationsConfigV5 } from './config.js';
2
+ export declare function buildConnectResponse(config: PollinationsConfigV5): Promise<string>;
@@ -0,0 +1,141 @@
1
+ export async function buildConnectResponse(config) {
2
+ const hasKey = !!config.apiKey;
3
+ const mode = config.mode;
4
+ let name = "Developer";
5
+ let tier = "anonymous";
6
+ if (hasKey) {
7
+ try {
8
+ const res = await fetch('https://gen.pollinations.ai/account/profile', {
9
+ headers: { 'Authorization': `Bearer ${config.apiKey}` }
10
+ });
11
+ if (res.ok) {
12
+ const data = await res.json();
13
+ if (data.name)
14
+ name = data.name;
15
+ tier = data.tier || "anonymous";
16
+ }
17
+ }
18
+ catch (e) {
19
+ // Ignorer l'erreur réseau et garder les valeurs par défaut
20
+ }
21
+ }
22
+ const emojis = {
23
+ microbe: '🦠', spore: '🍄', seed: '🌱', flower: '🌸', nectar: '🍯', anonymous: '👤'
24
+ };
25
+ const tierEmoji = emojis[tier] || '❓';
26
+ if (hasKey) {
27
+ return `## 🍯💚 PLUGIN POLLINATIONS CONNECTÉ 💚🍯
28
+
29
+ Bienvenue **${name}** sur le plugin Pollinations pour l'agent !
30
+ **Mode actuel** : \`${mode}\`
31
+
32
+ > **Your Tiers:** ${tierEmoji} ${tier.toUpperCase()}
33
+
34
+ ---
35
+
36
+ ### 🚀 Des Outils Multimédias Intégrés au Développement
37
+
38
+ Ce plugin vous permet de générer du code, des images, d'analyser des vidéos et interagir avec les meilleurs modèles d'Intelligence Artificielle de manière totalement transparente et intégrée à votre environnement de travail. Accédez aux capacités des LLMs de pointe, que ce soit via des requêtes de chat, la refonte de votre base de code, ou directement dans le terminal.
39
+
40
+ **Ce Que ce plugin vous apporte en plus ! :**
41
+
42
+ **🛠️ Outils Gratuits Intégrés (Toujours disponibles) :**
43
+ - \`gen_qrcode\` / \`gen_diagram\` / \`gen_palette\` : Outils visuels et dev.
44
+ - \`remove_background\` : Détourage d'image natif.
45
+ - \`extract_frames\` / \`extract_audio\` : Extraction rapide de contenu média.
46
+ - \`file_to_url\` : Hébergement instantané de vos fichiers locaux en ligne.
47
+
48
+ **💎 Outils Pollinations (Premium - Automatisés avec votre Clé) :**
49
+ - \`polli_gen_image\` : Génération d'images (Flux, Seedream, Gemini) + support Image-to-Image.
50
+ - \`polli_gen_video\` : Génération vidéo text-to-video / image-to-video (Veo, Wan, LTX...).
51
+ - \`polli_gen_audio\`/\`polli_stt\` : Transcription Whisper, Text-to-Speech ElevenLabs.
52
+ - \`polli_gen_music\` : Moteur de musique générative.
53
+ - \`polli_web_search\` : Recherche connectée pour étendre la base de contexte de l'agent.
54
+
55
+ - **Une configuration granulaire**, des modes de gestions de vos tokens et de vos outils, de la sécurisation des coûts des outils consommant du pollen...
56
+
57
+ ---
58
+
59
+ **Commandes rapides Terminal :**
60
+
61
+ | Commande | Description |
62
+ |----------|-------------|
63
+ | \`/pollinations usage\` | Solde Pollen + quota tier |
64
+ | \`/pollinations infos\` | Toutes les infos sur le Tier et l'achat Pollen |
65
+ | \`/pollinations models\` | Liste détaillée des modèles multimédia |
66
+ | \`/pollinations pricing\` | Tarifs en temps réel par modèle |
67
+ | \`/pollinations help\` | Lister toutes les commandes pollinations |
68
+
69
+ *(Note: Ces commandes locales ne sont disponibles que si le modèle courant fait partie de l'univers Pollinations).*
70
+
71
+ ---
72
+
73
+ **Ressources :**
74
+ - Dashboard : https://enter.pollinations.ai
75
+ - Discord : https://discord.gg/pollinations-ai-885844321461485618
76
+ - GitHub : https://github.com/fkom13/opencode-pollinations-plugin`;
77
+ }
78
+ let freeModelsText = `Modèles gratuits disponibles : \`openai-fast\`, \`gemini-fast\`, \`mistral\`, \`qwen-coder\`, \`nova-fast\``;
79
+ try {
80
+ const freeRes = await fetch('https://text.pollinations.ai/models', { signal: AbortSignal.timeout(4000) });
81
+ if (freeRes.ok) {
82
+ const freeData = await freeRes.json();
83
+ const modelsList = freeData.slice(0, 15).map((m) => `\`${m.name}\``).join(', ');
84
+ freeModelsText = `**Modèles gratuits actuellement en ligne** : ${modelsList} ...
85
+
86
+ *(Note : L'univers gratuit \`text.pollinations.ai\` est un bonus communautaire indépendant de l'API principale Enter. Il peut subir de fortes charges. En cas d'erreur 500/520, c'est une indisponibilité temporaire normale !)*`;
87
+ }
88
+ else {
89
+ freeModelsText = `*(L'API Legacy Free Universe communautaire est temporairement indisponible. Retentez plus tard !)*`;
90
+ }
91
+ }
92
+ catch (e) {
93
+ freeModelsText = `*(L'API Legacy Free Universe communautaire est temporairement indisponible. Retentez plus tard !)*`;
94
+ }
95
+ return `## 🌸 Bienvenue dans le Plugin Pollinations
96
+
97
+ **Accès gratuit immédiat — aucune clé requise**
98
+
99
+ Ce plugin offre un environnement complet de chat, de génération de code et de manipulation de médias (Génération Image, Vidéo, Audio, Outils d'extraction...).
100
+
101
+ Sélectionnez un modèle \`pollinations/free/*\` dans la liste et discutez pour commencer.
102
+ ${freeModelsText}
103
+
104
+ ---
105
+
106
+ ## 🚀 Agents et Outils Multimédias Intégrés au Développement
107
+
108
+ Claude Opus, GPT-5, Gemini 3, Génération Vidéo Veo & Wan, ElevenLabs Music... débloquez la puissance complète de l'API Pollinations !
109
+
110
+ Ce plugin adopte un modèle **BYOK** (Bring Your Own Key) : en utilisant votre propre clé API, l'Agent OpenCode gagne la capacité d'interagir directement avec des outils Premium en créant vos fichiers multimédias dans votre Espace de Travail.
111
+
112
+ **Étape 1 — Créer un compte avec 1.00 pollen Gratuit !**
113
+ Soutenez le plugin en passant par ce lien :
114
+ 👉 **https://enter.pollinations.ai/?ref=fkom13**
115
+
116
+ **Étape 2 — Générer votre clé API**
117
+ Dans la section **API Keys** sur \`enter.pollinations.ai\`, créez une clé **Secret** (\`sk_...\`).
118
+ ⚠️ **IMPORTANT** : Lors de la création de la clé, vous devez impérativement l'autoriser à consulter le compte et les usages pour pouvoir bénéficier de toutes les fonctionnalités avancées (protection Free-Tier/Wallet, Agent Guard).
119
+
120
+ **Étape 3 — Connecter la clé**
121
+ \`\`\`bash
122
+ /pollinations connect sk_votre_clé_ici
123
+ \`\`\`
124
+ *(La clé s'enregistre immédiatement dans votre environnement OpenCode, débloquant les modèles Pro !)*
125
+
126
+ ---
127
+
128
+ ## 💰 Système de Pollen et Tiers
129
+ Chaque développeur reçoit une **Subvention quotidienne gratuite (Tier Grant)** pour utiliser ces services Premium :
130
+ - 🦠 **Microbe** (0.1 pollen/jour) : Pour débloquer : S'inscrire
131
+ - 🍄 **Spore** (1 pollen/jour) : Pour débloquer : Vérification automatique (Vérifié à l'inscription)
132
+ - 🌱 **Seed** (3 pollen/jour) : Pour débloquer : 8+ points dev (Mise à niveau automatique hebdomadaire)
133
+ - 🌸 **Flower** (10 pollen/jour) : Pour débloquer : Publier une application (🌱 Doit être Seed en premier)
134
+ - 🍯 **Nectar** (20 pollen/jour) : Bientôt disponible 🔮
135
+
136
+ Une fois le quota gratuit épuisé, vous consommez le Pollen de votre portefeuille ($1 ≈ 1 Pollen, pas d'abonnement, pas d'expiration).
137
+
138
+ **Besoin d'aide ?**
139
+ - Tapez \`/pollinations help\` pour la liste des commandes.
140
+ - Discord Officiel : https://discord.gg/pollinations-ai-885844321461485618`;
141
+ }
@@ -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 {};