opencode-pollinations-plugin 5.4.13 → 5.4.15
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/dist/server/config.js +67 -39
- package/dist/server/proxy.js +19 -1
- package/package.json +1 -1
package/dist/server/config.js
CHANGED
|
@@ -47,50 +47,70 @@ export function loadConfig() {
|
|
|
47
47
|
}
|
|
48
48
|
function readConfigFromDisk() {
|
|
49
49
|
let config = { ...DEFAULT_CONFIG_V5 };
|
|
50
|
-
let
|
|
51
|
-
|
|
50
|
+
let finalKey = undefined;
|
|
51
|
+
let source = 'none';
|
|
52
|
+
// TIMESTAMP BASED PRIORITY LOGIC
|
|
53
|
+
// We want the most recently updated Valid Key to win.
|
|
54
|
+
let configTime = 0;
|
|
55
|
+
let authTime = 0;
|
|
52
56
|
try {
|
|
53
|
-
if (fs.existsSync(CONFIG_FILE))
|
|
57
|
+
if (fs.existsSync(CONFIG_FILE))
|
|
58
|
+
configTime = fs.statSync(CONFIG_FILE).mtime.getTime();
|
|
59
|
+
}
|
|
60
|
+
catch (e) { }
|
|
61
|
+
try {
|
|
62
|
+
if (fs.existsSync(AUTH_FILE))
|
|
63
|
+
authTime = fs.statSync(AUTH_FILE).mtime.getTime();
|
|
64
|
+
}
|
|
65
|
+
catch (e) { }
|
|
66
|
+
// 1. EXTRACT KEYS
|
|
67
|
+
let configKey = undefined;
|
|
68
|
+
if (fs.existsSync(CONFIG_FILE)) {
|
|
69
|
+
try {
|
|
54
70
|
const raw = fs.readFileSync(CONFIG_FILE, 'utf-8');
|
|
55
71
|
const custom = JSON.parse(raw);
|
|
56
|
-
config = { ...config, ...custom };
|
|
57
|
-
if (
|
|
58
|
-
|
|
72
|
+
config = { ...config, ...custom }; // Helper: We load the rest of config anyway
|
|
73
|
+
if (custom.apiKey && custom.apiKey.length > 5)
|
|
74
|
+
configKey = custom.apiKey;
|
|
59
75
|
}
|
|
76
|
+
catch (e) { }
|
|
60
77
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
// 2. Auth Store (Fallback ONLY if config.json didn't exist or we are in a clear state)
|
|
65
|
-
// If config.json exists, it is the source of truth. We shouldn't resurrect old keys from auth.json
|
|
66
|
-
// UNLESS config.json is "empty" (just created default).
|
|
67
|
-
// But how to know?
|
|
68
|
-
// New logic: If Custom Config was loaded (fs.exists(CONFIG_FILE)), we trust it.
|
|
69
|
-
// We only check Auth Store if NO custom config exists OR if custom config is explicitly "manual" and we want to auto-discover?
|
|
70
|
-
// User complaint: "Old key comes back".
|
|
71
|
-
// Fix: If config.json exists, we DO NOT check auth.json.
|
|
72
|
-
if (!fs.existsSync(CONFIG_FILE) && !keyFound) {
|
|
78
|
+
let authKey = undefined;
|
|
79
|
+
if (fs.existsSync(AUTH_FILE)) {
|
|
73
80
|
try {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
config.apiKey = key;
|
|
82
|
-
config.mode = 'pro';
|
|
83
|
-
keyFound = true;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
81
|
+
const raw = fs.readFileSync(AUTH_FILE, 'utf-8');
|
|
82
|
+
const authData = JSON.parse(raw);
|
|
83
|
+
const entry = authData['pollinations'] || authData['pollinations_enter'] || authData['pollinations_api_key'];
|
|
84
|
+
if (entry) {
|
|
85
|
+
const k = (typeof entry === 'object' && entry.key) ? entry.key : entry;
|
|
86
|
+
if (k && typeof k === 'string' && k.length > 10)
|
|
87
|
+
authKey = k;
|
|
86
88
|
}
|
|
87
89
|
}
|
|
88
|
-
catch (e) {
|
|
89
|
-
|
|
90
|
+
catch (e) { }
|
|
91
|
+
}
|
|
92
|
+
// 2. DETERMINE WINNER
|
|
93
|
+
// If both exist, newest wins. If one exists, it wins.
|
|
94
|
+
if (configKey && authKey) {
|
|
95
|
+
if (configTime >= authTime) {
|
|
96
|
+
finalKey = configKey;
|
|
97
|
+
source = 'config.json';
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
finalKey = authKey;
|
|
101
|
+
source = 'auth.json';
|
|
90
102
|
}
|
|
91
103
|
}
|
|
92
|
-
|
|
93
|
-
|
|
104
|
+
else if (configKey) {
|
|
105
|
+
finalKey = configKey;
|
|
106
|
+
source = 'config.json';
|
|
107
|
+
}
|
|
108
|
+
else if (authKey) {
|
|
109
|
+
finalKey = authKey;
|
|
110
|
+
source = 'auth.json';
|
|
111
|
+
}
|
|
112
|
+
// 3. Fallback to OpenCode Global Config (Lowest Priority)
|
|
113
|
+
if (!finalKey) {
|
|
94
114
|
try {
|
|
95
115
|
if (fs.existsSync(OPENCODE_CONFIG_FILE)) {
|
|
96
116
|
const raw = fs.readFileSync(OPENCODE_CONFIG_FILE, 'utf-8');
|
|
@@ -98,16 +118,24 @@ function readConfigFromDisk() {
|
|
|
98
118
|
const nativeKey = data?.provider?.pollinations?.options?.apiKey ||
|
|
99
119
|
data?.provider?.pollinations_enter?.options?.apiKey;
|
|
100
120
|
if (nativeKey && nativeKey.length > 5 && nativeKey !== 'dummy') {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
keyFound = true;
|
|
121
|
+
finalKey = nativeKey;
|
|
122
|
+
source = 'opencode.json';
|
|
104
123
|
}
|
|
105
124
|
}
|
|
106
125
|
}
|
|
107
126
|
catch (e) { }
|
|
108
127
|
}
|
|
109
|
-
|
|
110
|
-
|
|
128
|
+
// 4. APPLY
|
|
129
|
+
if (finalKey) {
|
|
130
|
+
config.apiKey = finalKey;
|
|
131
|
+
config.mode = 'pro';
|
|
132
|
+
// logConfig(`Loaded Key from ${source}`); // Debug
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
// Ensure no phantom key remains
|
|
136
|
+
delete config.apiKey;
|
|
137
|
+
if (config.mode === 'pro')
|
|
138
|
+
config.mode = 'manual';
|
|
111
139
|
}
|
|
112
140
|
return { ...config, version: PKG_VERSION };
|
|
113
141
|
}
|
package/dist/server/proxy.js
CHANGED
|
@@ -260,7 +260,25 @@ export async function handleChatCompletion(req, res, bodyRaw) {
|
|
|
260
260
|
// B. SAFETY NETS (The Core V5 Logic)
|
|
261
261
|
if (config.mode === 'alwaysfree') {
|
|
262
262
|
if (isEnterprise) {
|
|
263
|
-
|
|
263
|
+
// NEW: Paid Only Check for Always Free
|
|
264
|
+
// If the user asks for a 💎 Paid Only model while in Always Free, we BLOCK it to save wallet
|
|
265
|
+
// and fallback to free specific message.
|
|
266
|
+
try {
|
|
267
|
+
const homedir = process.env.HOME || '/tmp';
|
|
268
|
+
const standardPaidPath = path.join(homedir, '.pollinations', 'pollinations-paid-models.json');
|
|
269
|
+
if (fs.existsSync(standardPaidPath)) {
|
|
270
|
+
const paidModels = JSON.parse(fs.readFileSync(standardPaidPath, 'utf-8'));
|
|
271
|
+
if (paidModels.includes(actualModel)) {
|
|
272
|
+
log(`[SafetyNet] alwaysfree Mode: Request for Paid Only Model (${actualModel}). FALLBACK.`);
|
|
273
|
+
actualModel = config.fallbacks.free.main.replace('free/', '');
|
|
274
|
+
isEnterprise = false;
|
|
275
|
+
isFallbackActive = true;
|
|
276
|
+
fallbackReason = "Mode AlwaysFree actif: Ce modèle payant consomme du wallet. Passez en mode PRO.";
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
catch (e) { }
|
|
281
|
+
if (!isFallbackActive && quota.tier === 'error') {
|
|
264
282
|
log(`[SafetyNet] AlwaysFree Mode: Quota Check Failed. Switching to Free Fallback.`);
|
|
265
283
|
actualModel = config.fallbacks.free.main.replace('free/', '');
|
|
266
284
|
isEnterprise = false;
|
package/package.json
CHANGED