opencode-pollinations-plugin 6.1.0-beta.9 → 6.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/README.de.md +130 -0
  2. package/README.es.md +130 -0
  3. package/README.fr.md +130 -0
  4. package/README.it.md +130 -0
  5. package/README.md +87 -73
  6. package/dist/index.js +52 -161
  7. package/dist/locales/de.json +374 -0
  8. package/dist/locales/en.json +373 -0
  9. package/dist/locales/es.json +374 -0
  10. package/dist/locales/fr.json +373 -0
  11. package/dist/locales/index.d.ts +1 -0
  12. package/dist/locales/index.js +37 -0
  13. package/dist/locales/it.json +374 -0
  14. package/dist/server/commands.d.ts +6 -0
  15. package/dist/server/commands.js +394 -125
  16. package/dist/server/config.d.ts +34 -23
  17. package/dist/server/config.js +200 -108
  18. package/dist/server/connect-response.d.ts +2 -0
  19. package/dist/server/connect-response.js +59 -0
  20. package/dist/server/generate-config.d.ts +3 -30
  21. package/dist/server/generate-config.js +164 -106
  22. package/dist/server/index.d.ts +2 -1
  23. package/dist/server/index.js +124 -149
  24. package/dist/server/logger.d.ts +8 -0
  25. package/dist/server/logger.js +38 -0
  26. package/dist/server/models/cache.d.ts +35 -0
  27. package/dist/server/models/cache.js +160 -0
  28. package/dist/server/models/fetcher.d.ts +18 -0
  29. package/dist/server/models/fetcher.js +194 -0
  30. package/dist/server/models/index.d.ts +6 -0
  31. package/dist/server/models/index.js +5 -0
  32. package/dist/server/models/manual.d.ts +15 -0
  33. package/dist/server/models/manual.js +92 -0
  34. package/dist/server/models/types.d.ts +55 -0
  35. package/dist/server/models/types.js +7 -0
  36. package/dist/server/models/worker.d.ts +22 -0
  37. package/dist/server/models/worker.js +174 -0
  38. package/dist/server/pollinations-api.d.ts +11 -0
  39. package/dist/server/pollinations-api.js +21 -8
  40. package/dist/server/proxy.js +222 -307
  41. package/dist/server/quota.d.ts +2 -0
  42. package/dist/server/quota.js +89 -86
  43. package/dist/server/scripts/pollinations_pricing.d.ts +8 -0
  44. package/dist/server/scripts/pollinations_pricing.js +246 -0
  45. package/dist/server/scripts/test_cost_endpoints.d.ts +1 -0
  46. package/dist/server/scripts/test_cost_endpoints.js +61 -0
  47. package/dist/server/scripts/test_dynamic_pricing.d.ts +1 -0
  48. package/dist/server/scripts/test_dynamic_pricing.js +39 -0
  49. package/dist/server/scripts/test_freetier_audit.d.ts +11 -0
  50. package/dist/server/scripts/test_freetier_audit.js +215 -0
  51. package/dist/server/scripts/test_parallel_cost.d.ts +1 -0
  52. package/dist/server/scripts/test_parallel_cost.js +104 -0
  53. package/dist/server/toast.d.ts +7 -1
  54. package/dist/server/toast.js +43 -10
  55. package/dist/tools/design/gen_diagram.d.ts +2 -0
  56. package/dist/tools/design/gen_diagram.js +94 -0
  57. package/dist/tools/design/gen_palette.d.ts +2 -0
  58. package/dist/tools/design/gen_palette.js +182 -0
  59. package/dist/tools/design/gen_qrcode.d.ts +2 -0
  60. package/dist/tools/design/gen_qrcode.js +50 -0
  61. package/dist/tools/ffmpeg.d.ts +24 -0
  62. package/dist/tools/ffmpeg.js +54 -0
  63. package/dist/tools/index.d.ts +25 -0
  64. package/dist/tools/index.js +86 -0
  65. package/dist/tools/pollinations/beta_discovery.d.ts +9 -0
  66. package/dist/tools/pollinations/beta_discovery.js +201 -0
  67. package/dist/tools/pollinations/cost-guard.d.ts +38 -0
  68. package/dist/tools/pollinations/cost-guard.js +136 -0
  69. package/dist/tools/pollinations/deepsearch.d.ts +7 -0
  70. package/dist/tools/pollinations/deepsearch.js +80 -0
  71. package/dist/tools/pollinations/gen_audio.d.ts +18 -0
  72. package/dist/tools/pollinations/gen_audio.js +220 -0
  73. package/dist/tools/pollinations/gen_image.d.ts +11 -0
  74. package/dist/tools/pollinations/gen_image.js +211 -0
  75. package/dist/tools/pollinations/gen_music.d.ts +14 -0
  76. package/dist/tools/pollinations/gen_music.js +157 -0
  77. package/dist/tools/pollinations/gen_video.d.ts +16 -0
  78. package/dist/tools/pollinations/gen_video.js +249 -0
  79. package/dist/tools/pollinations/polli_config.d.ts +2 -0
  80. package/dist/tools/pollinations/polli_config.js +95 -0
  81. package/dist/tools/pollinations/polli_gen_confirm.d.ts +2 -0
  82. package/dist/tools/pollinations/polli_gen_confirm.js +48 -0
  83. package/dist/tools/pollinations/polli_status.d.ts +2 -0
  84. package/dist/tools/pollinations/polli_status.js +31 -0
  85. package/dist/tools/pollinations/polli_web_search.d.ts +15 -0
  86. package/dist/tools/pollinations/polli_web_search.js +126 -0
  87. package/dist/tools/pollinations/search_crawl_scrape.d.ts +7 -0
  88. package/dist/tools/pollinations/search_crawl_scrape.js +85 -0
  89. package/dist/tools/pollinations/shared.d.ts +181 -0
  90. package/dist/tools/pollinations/shared.js +758 -0
  91. package/dist/tools/pollinations/test_estimators.d.ts +1 -0
  92. package/dist/tools/pollinations/test_estimators.js +22 -0
  93. package/dist/tools/pollinations/transcribe_audio.d.ts +13 -0
  94. package/dist/tools/pollinations/transcribe_audio.js +171 -0
  95. package/dist/tools/power/extract_audio.d.ts +2 -0
  96. package/dist/tools/power/extract_audio.js +179 -0
  97. package/dist/tools/power/extract_frames.d.ts +2 -0
  98. package/dist/tools/power/extract_frames.js +237 -0
  99. package/dist/tools/power/file_to_url.d.ts +2 -0
  100. package/dist/tools/power/file_to_url.js +217 -0
  101. package/dist/tools/power/remove_background.d.ts +2 -0
  102. package/dist/tools/power/remove_background.js +404 -0
  103. package/dist/tools/power/rmbg_keys.d.ts +2 -0
  104. package/dist/tools/power/rmbg_keys.js +79 -0
  105. package/dist/tools/shared.d.ts +30 -0
  106. package/dist/tools/shared.js +80 -0
  107. package/package.json +9 -3
  108. package/dist/server/models-seed.d.ts +0 -18
  109. 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,28 @@ 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;
31
+ lang?: string;
25
32
  }
26
- export declare function loadConfig(): PollinationsConfigV6;
27
- export declare function saveConfig(updates: Partial<PollinationsConfigV6>): {
33
+ export declare function loadConfig(): PollinationsConfigV5;
34
+ export declare function saveConfig(updates: Partial<PollinationsConfigV5>): {
28
35
  version: string;
29
- mode: "manual" | "economy" | "pro";
36
+ mode: "manual" | "alwaysfree" | "pro";
30
37
  apiKey?: string;
31
38
  keyHasAccessToProfile?: boolean;
32
39
  gui: {
@@ -35,19 +42,23 @@ export declare function saveConfig(updates: Partial<PollinationsConfigV6>): {
35
42
  };
36
43
  thresholds: {
37
44
  tier: number;
38
- wallet_warn: number;
39
- wallet_stop: number;
45
+ wallet: number;
40
46
  };
41
47
  fallbacks: {
42
- economy: string;
43
- pro: string;
44
- };
45
- session: {
46
- wallet_initial?: number;
47
- session_start?: string;
48
+ free: {
49
+ main: string;
50
+ agent: string;
51
+ };
52
+ enter: {
53
+ agent: string;
54
+ };
48
55
  };
49
56
  enablePaidTools: boolean;
57
+ costThreshold: number;
58
+ costConfirmationRequired: boolean;
50
59
  statusBar: boolean;
60
+ costEstimator: boolean;
61
+ lang?: string;
51
62
  };
52
- export declare function initSessionWallet(walletBalance: number): void;
53
- export declare function getWalletWarnPercent(): number;
63
+ export declare function saveKeyToAuthJson(key: string): boolean;
64
+ 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)) {
@@ -17,118 +64,113 @@ try {
17
64
  PKG_VERSION = pkg.version;
18
65
  }
19
66
  }
20
- catch (e) { }
21
- const DEFAULT_CONFIG_V6 = {
67
+ catch (e) {
68
+ logSystem(`[Config] Error loading package version: ${e}`);
69
+ }
70
+ const DEFAULT_CONFIG_V5 = {
22
71
  version: PKG_VERSION,
23
- mode: 'economy', // Défaut: economy (protège le wallet)
72
+ mode: 'manual',
24
73
  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
- },
74
+ thresholds: { tier: 10, wallet: 5 },
30
75
  fallbacks: {
31
- economy: 'nova-fast',
32
- pro: 'qwen-coder'
76
+ free: { main: 'free/mistral', agent: 'free/openai-fast' },
77
+ enter: { agent: 'free/openai-fast' }
33
78
  },
34
- session: {},
35
79
  enablePaidTools: false,
36
- keyHasAccessToProfile: true,
37
- statusBar: true
80
+ costThreshold: 0.15, // Default 0.15 🌻
81
+ costConfirmationRequired: true, // Ask confirmation when cost exceeds threshold
82
+ keyHasAccessToProfile: true, // Default true for legacy keys
83
+ statusBar: true,
84
+ costEstimator: true, // Show cost estimates by default
85
+ lang: 'en', // Default language is English
38
86
  };
87
+ import { log as logSystem } from './logger.js';
39
88
  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
- // Remove obsolete 'enter' fallback
63
- if (config.fallbacks?.enter) {
64
- delete config.fallbacks.enter;
65
- logConfig('[Migration] Removed obsolete fallbacks.enter');
66
- }
67
- // Migrate old wallet threshold
68
- if (config.thresholds?.wallet) {
69
- if (!config.thresholds.wallet_warn) {
70
- config.thresholds.wallet_warn = config.thresholds.wallet;
71
- }
72
- delete config.thresholds.wallet;
73
- logConfig('[Migration] thresholds.wallet → thresholds.wallet_warn');
74
- }
75
- return config;
89
+ logSystem(`[Config] ${msg}`);
76
90
  }
77
91
  // SIMPLE LOAD (Direct Disk Read - No Caching, No Watchers)
92
+ // This ensures the Proxy ALWAYS sees the latest state from auth.json
78
93
  export function loadConfig() {
79
94
  return readConfigFromDisk();
80
95
  }
81
96
  function readConfigFromDisk() {
82
- let config = { ...DEFAULT_CONFIG_V6 };
97
+ let config = { ...DEFAULT_CONFIG_V5 };
83
98
  let finalKey = undefined;
84
99
  let source = 'none';
100
+ // TIMESTAMP BASED PRIORITY LOGIC
101
+ // We want the most recently updated Valid Key to win.
85
102
  let configTime = 0;
86
103
  let authTime = 0;
87
104
  try {
88
105
  if (fs.existsSync(CONFIG_FILE))
89
106
  configTime = fs.statSync(CONFIG_FILE).mtime.getTime();
90
107
  }
91
- catch (e) { }
108
+ catch (e) {
109
+ logSystem(`[Config] Error stat config: ${e}`);
110
+ }
111
+ try {
112
+ if (fs.existsSync(CONFIG_FILE))
113
+ configTime = fs.statSync(CONFIG_FILE).mtime.getTime();
114
+ }
115
+ catch (e) {
116
+ logSystem(`[Config] Error stat config: ${e}`);
117
+ }
92
118
  try {
93
- if (fs.existsSync(AUTH_FILE))
94
- authTime = fs.statSync(AUTH_FILE).mtime.getTime();
119
+ for (const f of EXTERNAL_PATHS.auth) {
120
+ if (fs.existsSync(f)) {
121
+ authTime = Math.max(authTime, fs.statSync(f).mtime.getTime());
122
+ }
123
+ }
124
+ }
125
+ catch (e) {
126
+ logSystem(`[Config] Error stat auth candidates: ${e}`);
95
127
  }
96
- catch (e) { }
128
+ // 1. EXTRACT KEYS
97
129
  // 1. EXTRACT KEYS
98
130
  let configKey = undefined;
99
131
  if (fs.existsSync(CONFIG_FILE)) {
100
132
  try {
101
133
  const raw = fs.readFileSync(CONFIG_FILE, 'utf-8');
102
134
  const custom = JSON.parse(raw);
103
- const migrated = migrateConfig(custom);
104
- // DEEP MERGE for nested objects to preserve defaults vs overrides
105
- config = {
106
- ...config,
107
- ...migrated,
108
- thresholds: { ...config.thresholds, ...(migrated.thresholds || {}) },
109
- fallbacks: { ...config.fallbacks, ...(migrated.fallbacks || {}) },
110
- gui: { ...config.gui, ...(migrated.gui || {}) }
111
- };
135
+ config = { ...config, ...custom }; // Helper: We load the rest of config anyway
112
136
  if (custom.apiKey && custom.apiKey.length > 5)
113
137
  configKey = custom.apiKey;
114
138
  }
115
- catch (e) { }
139
+ catch (e) {
140
+ logConfig(`ERROR reading config.json: ${e}`);
141
+ // Backup corrupt file to avoid overwrite loop
142
+ try {
143
+ fs.copyFileSync(CONFIG_FILE, CONFIG_FILE + '.corrupt');
144
+ }
145
+ catch (e) {
146
+ logSystem(`[Config] Error copying corrupt config: ${e}`);
147
+ }
148
+ }
116
149
  }
117
150
  let authKey = undefined;
118
- if (fs.existsSync(AUTH_FILE)) {
119
- try {
120
- const raw = fs.readFileSync(AUTH_FILE, 'utf-8');
121
- const authData = JSON.parse(raw);
122
- const entry = authData['pollinations'] || authData['pollinations_enter'] || authData['pollinations_api_key'];
123
- if (entry) {
124
- const k = (typeof entry === 'object' && entry.key) ? entry.key : entry;
125
- if (k && typeof k === 'string' && k.length > 10)
126
- authKey = k;
151
+ // Check all auth candidates
152
+ for (const authFile of EXTERNAL_PATHS.auth) {
153
+ if (fs.existsSync(authFile)) {
154
+ try {
155
+ authTime = Math.max(authTime, fs.statSync(authFile).mtime.getTime()); // Track newest
156
+ const raw = fs.readFileSync(authFile, 'utf-8');
157
+ const authData = JSON.parse(raw);
158
+ const entry = authData['pollinations'] || authData['pollinations_enter'] || authData['pollinations_api_key'];
159
+ if (entry) {
160
+ const k = (typeof entry === 'object' && entry.key) ? entry.key : entry;
161
+ if (k && typeof k === 'string' && k.length > 10) {
162
+ authKey = k;
163
+ break; // Found a key, stop looking (priority to first found? or newest? First in list is Linux default so ok)
164
+ }
165
+ }
166
+ }
167
+ catch (e) {
168
+ logConfig(`ERROR reading auth candidate ${authFile}: ${e}`);
127
169
  }
128
170
  }
129
- catch (e) { }
130
171
  }
131
172
  // 2. DETERMINE WINNER
173
+ // If both exist, newest wins. If one exists, it wins.
132
174
  if (configKey && authKey) {
133
175
  if (configTime >= authTime) {
134
176
  finalKey = configKey;
@@ -150,25 +192,37 @@ function readConfigFromDisk() {
150
192
  // 3. Fallback to OpenCode Global Config (Lowest Priority)
151
193
  if (!finalKey) {
152
194
  try {
153
- if (fs.existsSync(OPENCODE_CONFIG_FILE)) {
154
- const raw = fs.readFileSync(OPENCODE_CONFIG_FILE, 'utf-8');
155
- const data = JSON.parse(raw);
156
- const nativeKey = data?.provider?.pollinations?.options?.apiKey ||
157
- data?.provider?.pollinations_enter?.options?.apiKey;
158
- if (nativeKey && nativeKey.length > 5 && nativeKey !== 'dummy') {
159
- finalKey = nativeKey;
160
- source = 'opencode.json';
195
+ for (const configFile of EXTERNAL_PATHS.config) {
196
+ if (fs.existsSync(configFile)) {
197
+ const raw = fs.readFileSync(configFile, 'utf-8');
198
+ const data = JSON.parse(raw);
199
+ const nativeKey = data?.provider?.pollinations?.options?.apiKey ||
200
+ data?.provider?.pollinations_enter?.options?.apiKey;
201
+ if (nativeKey && nativeKey.length > 5 && nativeKey !== 'dummy') {
202
+ finalKey = nativeKey;
203
+ source = 'opencode_global';
204
+ break;
205
+ }
161
206
  }
162
207
  }
163
208
  }
164
- catch (e) { }
209
+ catch (e) {
210
+ logSystem(`[Config] Error reading global override config: ${e}`);
211
+ }
165
212
  }
166
213
  // 4. APPLY
167
214
  if (finalKey) {
168
215
  config.apiKey = finalKey;
216
+ // config.mode = 'pro'; // REMOVED: Mode is decoupled from Key presence.
169
217
  }
170
218
  else {
219
+ // Ensure no phantom key remains
171
220
  delete config.apiKey;
221
+ // if (config.mode === 'pro') config.mode = 'manual'; // OPTIONAL: Downgrade if no key? User says "No link".
222
+ // Actually, if I am in PRO mode and lose my key, I am broken. Falling back to manual is safer?
223
+ // User said "Manual mode is like standard API".
224
+ // Let's REMOVE this auto-downgrade too to be strictly "Decoupled".
225
+ // If user is in PRO without key, they get "Missing Key" error, which is correct.
172
226
  }
173
227
  return { ...config, version: PKG_VERSION };
174
228
  }
@@ -176,11 +230,10 @@ export function saveConfig(updates) {
176
230
  try {
177
231
  const current = readConfigFromDisk();
178
232
  const updated = { ...current, ...updates, version: PKG_VERSION };
179
- if (!fs.existsSync(CONFIG_DIR_POLLI)) {
180
- fs.mkdirSync(CONFIG_DIR_POLLI, { recursive: true });
233
+ if (!fs.existsSync(CONFIG_DIR)) {
234
+ fs.mkdirSync(CONFIG_DIR, { recursive: true });
181
235
  }
182
236
  fs.writeFileSync(CONFIG_FILE, JSON.stringify(updated, null, 2));
183
- logConfig(`[SaveConfig] Updated: ${Object.keys(updates).join(', ')}`);
184
237
  return updated;
185
238
  }
186
239
  catch (e) {
@@ -188,23 +241,62 @@ export function saveConfig(updates) {
188
241
  throw e;
189
242
  }
190
243
  }
191
- // SESSION WALLET TRACKING
192
- export function initSessionWallet(walletBalance) {
193
- const config = loadConfig();
194
- if (!config.session.wallet_initial) {
195
- saveConfig({
196
- session: {
197
- wallet_initial: walletBalance,
198
- session_start: new Date().toISOString()
244
+ // === NATIVE AUTH SYNC ===
245
+ export function saveKeyToAuthJson(key) {
246
+ let success = false;
247
+ for (const authFile of EXTERNAL_PATHS.auth) {
248
+ try {
249
+ let authData = {};
250
+ if (fs.existsSync(authFile)) {
251
+ authData = JSON.parse(fs.readFileSync(authFile, 'utf-8'));
252
+ }
253
+ else {
254
+ // Ensure directory exists if we create a new auth.json
255
+ fs.mkdirSync(path.dirname(authFile), { recursive: true });
199
256
  }
200
- });
201
- logConfig(`[Session] Wallet initial stocké: $${walletBalance}`);
257
+ // Set the key (OpenCode standard struct)
258
+ authData['pollinations'] = {
259
+ type: "api",
260
+ key: key
261
+ };
262
+ fs.writeFileSync(authFile, JSON.stringify(authData, null, 2), 'utf-8');
263
+ logConfig(`Synchronized API key to native auth file: ${authFile}`);
264
+ success = true;
265
+ // Only write to the first valid one we find/create, or write to all existing?
266
+ // Usually writing to all existing ones is safest to avoid desync
267
+ }
268
+ catch (e) {
269
+ logConfig(`Failed to sync to auth file ${authFile}: ${e}`);
270
+ }
202
271
  }
272
+ return success;
203
273
  }
204
- export function getWalletWarnPercent() {
205
- const config = loadConfig();
206
- const initial = config.session.wallet_initial;
207
- if (!initial || initial <= 0)
208
- return 100; // No reference = no warning
209
- return config.thresholds.wallet_warn;
274
+ // === MIGRATION UTIL ===
275
+ export function migrateLegacyConfig() {
276
+ try {
277
+ const legacyDir = path.join(os.homedir(), '.pollinations');
278
+ const newDir = getConfigDir();
279
+ if (fs.existsSync(legacyDir) && legacyDir !== newDir) {
280
+ logConfig(`Migrating legacy config from ${legacyDir} to ${newDir}`);
281
+ if (!fs.existsSync(newDir))
282
+ fs.mkdirSync(newDir, { recursive: true });
283
+ const files = fs.readdirSync(legacyDir);
284
+ for (const file of files) {
285
+ const srcPath = path.join(legacyDir, file);
286
+ const destPath = path.join(newDir, file);
287
+ // Don't overwrite existing new files (priority to new system)
288
+ if (!fs.existsSync(destPath)) {
289
+ // Check if it's a file
290
+ if (fs.statSync(srcPath).isFile()) {
291
+ fs.copyFileSync(srcPath, destPath); // Copy first
292
+ // fs.unlinkSync(srcPath); // Optional: Delete old? Let's keep for safety for now.
293
+ logConfig(`Migrated: ${file}`);
294
+ }
295
+ }
296
+ }
297
+ }
298
+ }
299
+ catch (e) {
300
+ logConfig(`Migration Error: ${e}`);
301
+ }
210
302
  }
@@ -0,0 +1,2 @@
1
+ import { PollinationsConfigV5 } from './config.js';
2
+ export declare function buildConnectResponse(config: PollinationsConfigV5): Promise<string>;
@@ -0,0 +1,59 @@
1
+ import { t } from '../locales/index.js';
2
+ export async function buildConnectResponse(config) {
3
+ const hasKey = !!config.apiKey;
4
+ const mode = config.mode;
5
+ let name = "Developer";
6
+ let tier = "anonymous";
7
+ if (hasKey) {
8
+ try {
9
+ const res = await fetch('https://gen.pollinations.ai/account/profile', {
10
+ headers: { 'Authorization': `Bearer ${config.apiKey}` }
11
+ });
12
+ if (res.ok) {
13
+ const data = await res.json();
14
+ if (data.name)
15
+ name = data.name;
16
+ tier = data.tier || "anonymous";
17
+ }
18
+ }
19
+ catch (e) {
20
+ // Ignorer l'erreur réseau et garder les valeurs par défaut
21
+ }
22
+ }
23
+ const emojis = {
24
+ microbe: '🦠', spore: '🍄', seed: '🌱', flower: '🌸', nectar: '🍯', anonymous: '👤'
25
+ };
26
+ const tierEmoji = emojis[tier] || '❓';
27
+ if (hasKey) {
28
+ return `${t('connect_response.title_key', { name, mode })}
29
+
30
+ > **Your Tiers:** ${tierEmoji} ${tier.toUpperCase()}
31
+
32
+ ---
33
+
34
+ ${t('connect_response.tools_intro')}
35
+
36
+ ---
37
+
38
+ ${t('connect_response.terminal_cmds')}
39
+ ---
40
+
41
+ ${t('connect_response.resources')}`;
42
+ }
43
+ let freeModelsText = `Modèles gratuits disponibles : \`openai-fast\`, \`gemini-fast\`, \`mistral\`, \`qwen-coder\`, \`nova-fast\``;
44
+ try {
45
+ const freeRes = await fetch('https://text.pollinations.ai/models', { signal: AbortSignal.timeout(4000) });
46
+ if (freeRes.ok) {
47
+ const freeData = await freeRes.json();
48
+ const modelsList = freeData.slice(0, 15).map((m) => `\`${m.name}\``).join(', ');
49
+ freeModelsText = t('connect_response.free_models_success', { models: modelsList });
50
+ }
51
+ else {
52
+ freeModelsText = t('connect_response.free_models_error');
53
+ }
54
+ }
55
+ catch (e) {
56
+ freeModelsText = t('connect_response.free_models_error');
57
+ }
58
+ return t('connect_response.onboarding', { freeText: freeModelsText });
59
+ }
@@ -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 {};