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.
- package/README.md +242 -62
- package/dist/index.js +68 -159
- package/dist/server/commands.d.ts +6 -0
- package/dist/server/commands.js +400 -71
- package/dist/server/config.d.ts +32 -23
- package/dist/server/config.js +183 -99
- package/dist/server/connect-response.d.ts +2 -0
- package/dist/server/connect-response.js +141 -0
- package/dist/server/generate-config.d.ts +3 -30
- package/dist/server/generate-config.js +164 -106
- package/dist/server/index.d.ts +2 -1
- package/dist/server/index.js +124 -149
- package/dist/server/logger.d.ts +8 -0
- package/dist/server/logger.js +36 -0
- package/dist/server/models/cache.d.ts +35 -0
- package/dist/server/models/cache.js +160 -0
- package/dist/server/models/fetcher.d.ts +18 -0
- package/dist/server/models/fetcher.js +150 -0
- package/dist/server/models/index.d.ts +6 -0
- package/dist/server/models/index.js +5 -0
- package/dist/server/models/manual.d.ts +15 -0
- package/dist/server/models/manual.js +92 -0
- package/dist/server/models/types.d.ts +55 -0
- package/dist/server/models/types.js +7 -0
- package/dist/server/models/worker.d.ts +21 -0
- package/dist/server/models/worker.js +97 -0
- package/dist/server/pollinations-api.d.ts +11 -0
- package/dist/server/pollinations-api.js +21 -8
- package/dist/server/proxy.js +223 -160
- package/dist/server/quota.d.ts +2 -0
- package/dist/server/quota.js +89 -86
- package/dist/server/scripts/pollinations_pricing.d.ts +8 -0
- package/dist/server/scripts/pollinations_pricing.js +246 -0
- package/dist/server/scripts/test_cost_endpoints.d.ts +1 -0
- package/dist/server/scripts/test_cost_endpoints.js +61 -0
- package/dist/server/scripts/test_dynamic_pricing.d.ts +1 -0
- package/dist/server/scripts/test_dynamic_pricing.js +39 -0
- package/dist/server/scripts/test_freetier_audit.d.ts +11 -0
- package/dist/server/scripts/test_freetier_audit.js +215 -0
- package/dist/server/scripts/test_parallel_cost.d.ts +1 -0
- package/dist/server/scripts/test_parallel_cost.js +104 -0
- package/dist/server/toast.d.ts +7 -1
- package/dist/server/toast.js +43 -10
- 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/ffmpeg.d.ts +24 -0
- package/dist/tools/ffmpeg.js +54 -0
- package/dist/tools/index.d.ts +24 -0
- package/dist/tools/index.js +83 -0
- package/dist/tools/pollinations/beta_discovery.d.ts +9 -0
- package/dist/tools/pollinations/beta_discovery.js +197 -0
- package/dist/tools/pollinations/cost-guard.d.ts +38 -0
- package/dist/tools/pollinations/cost-guard.js +141 -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 +246 -0
- package/dist/tools/pollinations/gen_image.d.ts +11 -0
- package/dist/tools/pollinations/gen_image.js +225 -0
- package/dist/tools/pollinations/gen_music.d.ts +14 -0
- package/dist/tools/pollinations/gen_music.js +180 -0
- package/dist/tools/pollinations/gen_video.d.ts +16 -0
- package/dist/tools/pollinations/gen_video.js +256 -0
- package/dist/tools/pollinations/polli_gen_confirm.d.ts +2 -0
- package/dist/tools/pollinations/polli_gen_confirm.js +48 -0
- package/dist/tools/pollinations/polli_status.d.ts +2 -0
- package/dist/tools/pollinations/polli_status.js +31 -0
- package/dist/tools/pollinations/polli_web_search.d.ts +15 -0
- package/dist/tools/pollinations/polli_web_search.js +164 -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 +165 -0
- package/dist/tools/pollinations/shared.js +665 -0
- package/dist/tools/pollinations/test_estimators.d.ts +1 -0
- package/dist/tools/pollinations/test_estimators.js +22 -0
- package/dist/tools/pollinations/transcribe_audio.d.ts +13 -0
- package/dist/tools/pollinations/transcribe_audio.js +194 -0
- package/dist/tools/power/extract_audio.d.ts +2 -0
- package/dist/tools/power/extract_audio.js +179 -0
- package/dist/tools/power/extract_frames.d.ts +2 -0
- package/dist/tools/power/extract_frames.js +237 -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 +366 -0
- package/dist/tools/power/rmbg_keys.d.ts +2 -0
- package/dist/tools/power/rmbg_keys.js +79 -0
- package/dist/tools/shared.d.ts +30 -0
- package/dist/tools/shared.js +80 -0
- package/package.json +10 -4
- package/dist/server/models-seed.d.ts +0 -18
- package/dist/server/models-seed.js +0 -55
package/dist/server/config.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
export
|
|
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' | '
|
|
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
|
-
|
|
13
|
-
wallet_stop: number;
|
|
15
|
+
wallet: number;
|
|
14
16
|
};
|
|
15
17
|
fallbacks: {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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():
|
|
27
|
-
export declare function saveConfig(updates: Partial<
|
|
32
|
+
export declare function loadConfig(): PollinationsConfigV5;
|
|
33
|
+
export declare function saveConfig(updates: Partial<PollinationsConfigV5>): {
|
|
28
34
|
version: string;
|
|
29
|
-
mode: "manual" | "
|
|
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
|
-
|
|
39
|
-
wallet_stop: number;
|
|
44
|
+
wallet: number;
|
|
40
45
|
};
|
|
41
46
|
fallbacks: {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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
|
|
53
|
-
export declare function
|
|
61
|
+
export declare function saveKeyToAuthJson(key: string): boolean;
|
|
62
|
+
export declare function migrateLegacyConfig(): void;
|
package/dist/server/config.js
CHANGED
|
@@ -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
|
-
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
|
|
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 = '
|
|
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
|
|
68
|
+
const DEFAULT_CONFIG_V5 = {
|
|
22
69
|
version: PKG_VERSION,
|
|
23
|
-
mode: '
|
|
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
|
-
|
|
32
|
-
|
|
74
|
+
free: { main: 'free/mistral', agent: 'free/openai-fast' },
|
|
75
|
+
enter: { agent: 'free/openai-fast' }
|
|
33
76
|
},
|
|
34
|
-
session: {},
|
|
35
77
|
enablePaidTools: false,
|
|
36
|
-
|
|
37
|
-
|
|
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
|
-
|
|
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 = { ...
|
|
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(
|
|
89
|
-
|
|
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
|
-
|
|
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
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
const
|
|
120
|
-
|
|
121
|
-
|
|
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
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
data?.provider?.
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
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(
|
|
175
|
-
fs.mkdirSync(
|
|
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
|
-
//
|
|
187
|
-
export function
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
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
|
-
|
|
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
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
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,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 {};
|