opencode-pollinations-plugin 6.4.2 → 6.4.3
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/commands.js +7 -1
- package/dist/server/config.d.ts +2 -0
- package/dist/server/config.js +1 -0
- package/dist/server/generate-config.js +4 -4
- package/dist/server/models/worker.js +8 -7
- package/dist/server/proxy.js +7 -1
- package/dist/server/quota.d.ts +6 -0
- package/dist/server/quota.js +35 -1
- package/dist/tools/pollinations/polli_config.js +4 -1
- package/package.json +1 -1
package/dist/server/commands.js
CHANGED
|
@@ -656,6 +656,7 @@ ${t('commands.config.table_divider')}
|
|
|
656
656
|
| **costThreshold**| \`${config.costThreshold ?? 0.15} 🌻\` | ${t('commands.config.costThreshold_role')} | \`/poll config costThreshold <X>\` |
|
|
657
657
|
| **cost_estimator**| \`${config.costEstimator ?? true}\` | ${t('commands.config.cost_estimator_role')} | \`/poll config cost_estimator <true/false>\` |
|
|
658
658
|
| **refillOverride**| \`${config.refillOverride ?? 'auto (déduit)'}\` | Quest Pollen refill horaire | \`/poll config refillOverride <0.01/0.15/0.4/0.8/10>\` |
|
|
659
|
+
| **questStashInFreeMode**| \`${config.questStashInFreeMode ?? true}\` | Compte le stash dans alwaysfree | \`/poll config questStashInFreeMode <true/false>\` |
|
|
659
660
|
| **fallbacks.free.main** | \`${config.fallbacks?.free?.main || 'free/mistral'}\` | ${t('commands.config.fallback_main_role')} | \`/poll fallback <main> <agent>\` |
|
|
660
661
|
| **fallbacks.free.agent** | \`${config.fallbacks?.free?.agent || 'free/openai-fast'}\`| ${t('commands.config.fallback_agent_role')} | \`/poll fallback <main> <agent>\` |
|
|
661
662
|
| **fallbacks.enter.agent** | \`${config.fallbacks?.enter?.agent || 'free/openai-fast'}\`| ${t('commands.config.fallback_enter_role')} | *${t('commands.config.managed_auto')}* |
|
|
@@ -764,9 +765,14 @@ ${t('commands.config.table_divider')}
|
|
|
764
765
|
saveConfig({ refillOverride: override });
|
|
765
766
|
return { handled: true, response: `✅ refillOverride = ${override} 🌻/h` };
|
|
766
767
|
}
|
|
768
|
+
if (key === 'questStashInFreeMode' && value) {
|
|
769
|
+
const enabled = value === 'true';
|
|
770
|
+
saveConfig({ questStashInFreeMode: enabled });
|
|
771
|
+
return { handled: true, response: `✅ questStashInFreeMode = ${enabled}${enabled ? ' (le stash Quest compte comme free)' : ' (seul le refill horaire compte)'}` };
|
|
772
|
+
}
|
|
767
773
|
return {
|
|
768
774
|
handled: true,
|
|
769
|
-
error: `Clé inconnue: ${key}. Clés: status_gui, logs_gui, threshold_tier, threshold_wallet, status_bar, cost_estimator, enablePaidTools, costThreshold, costConfirmationRequired, refillOverride, lang`
|
|
775
|
+
error: `Clé inconnue: ${key}. Clés: status_gui, logs_gui, threshold_tier, threshold_wallet, status_bar, cost_estimator, enablePaidTools, costThreshold, costConfirmationRequired, refillOverride, questStashInFreeMode, lang`
|
|
770
776
|
};
|
|
771
777
|
}
|
|
772
778
|
function handleHelpCommand() {
|
package/dist/server/config.d.ts
CHANGED
|
@@ -29,6 +29,7 @@ export interface PollinationsConfigV5 {
|
|
|
29
29
|
statusBar: boolean;
|
|
30
30
|
costEstimator: boolean;
|
|
31
31
|
refillOverride?: number;
|
|
32
|
+
questStashInFreeMode?: boolean;
|
|
32
33
|
lang?: string;
|
|
33
34
|
}
|
|
34
35
|
export declare function loadConfig(): PollinationsConfigV5;
|
|
@@ -60,6 +61,7 @@ export declare function saveConfig(updates: Partial<PollinationsConfigV5>): {
|
|
|
60
61
|
statusBar: boolean;
|
|
61
62
|
costEstimator: boolean;
|
|
62
63
|
refillOverride?: number;
|
|
64
|
+
questStashInFreeMode?: boolean;
|
|
63
65
|
lang?: string;
|
|
64
66
|
};
|
|
65
67
|
export declare function saveKeyToAuthJson(key: string): boolean;
|
package/dist/server/config.js
CHANGED
|
@@ -82,6 +82,7 @@ const DEFAULT_CONFIG_V5 = {
|
|
|
82
82
|
keyHasAccessToProfile: true, // Default true for legacy keys
|
|
83
83
|
statusBar: true,
|
|
84
84
|
costEstimator: true, // Show cost estimates by default
|
|
85
|
+
questStashInFreeMode: true, // Count quest stash as free in alwaysfree
|
|
85
86
|
lang: 'en', // Default language is English
|
|
86
87
|
};
|
|
87
88
|
import { log as logSystem } from './logger.js';
|
|
@@ -87,12 +87,12 @@ export async function generatePollinationsConfig(forceApiKey, forceStrict = fals
|
|
|
87
87
|
const enterList = ModelRegistry.list('text');
|
|
88
88
|
const paidModels = [];
|
|
89
89
|
enterList.forEach((m) => {
|
|
90
|
-
if (m.tools ===
|
|
91
|
-
return; //
|
|
90
|
+
if (m.tools !== true || m.community === true)
|
|
91
|
+
return; // Exclude non-tool and community models
|
|
92
92
|
const mapped = mapModel(m, 'enter/', '');
|
|
93
93
|
modelsOutput.push(mapped);
|
|
94
94
|
if (m.paid_only) {
|
|
95
|
-
paidModels.push(mapped.id.replace('enter/', ''));
|
|
95
|
+
paidModels.push(mapped.id.replace('enter/', ''));
|
|
96
96
|
}
|
|
97
97
|
});
|
|
98
98
|
log(`Total models (Free+Pro): ${modelsOutput.length}`);
|
|
@@ -207,7 +207,7 @@ function mapModel(raw, prefix, namePrefix) {
|
|
|
207
207
|
}
|
|
208
208
|
}
|
|
209
209
|
// 2. REASONING VARIANTS — format @ai-sdk/openai-compatible: { reasoningEffort: "level" }
|
|
210
|
-
if (raw.reasoning === true || rawId.includes('thinking') || rawId.includes('reasoning')) {
|
|
210
|
+
if (raw.reasoning === true || raw.capabilities?.includes('reasoning') || rawId.includes('thinking') || rawId.includes('reasoning')) {
|
|
211
211
|
modelObj.variants = {
|
|
212
212
|
...modelObj.variants,
|
|
213
213
|
low: { reasoningEffort: 'low' },
|
|
@@ -58,12 +58,11 @@ export class ToolRegistryWorker {
|
|
|
58
58
|
videoTable += `| Modèle | Source I/O | Audio | 1 pollen ≈ | Specs |\n`;
|
|
59
59
|
videoTable += `|--------|------------|-------|------------|-------|\n`;
|
|
60
60
|
for (const m of videoModels) {
|
|
61
|
-
// Estimation pour une vidéo moyenne de 6 secondes
|
|
62
61
|
const cost = estimateVideoCost(m.name, 6);
|
|
63
62
|
const price = cost ? `${per1pollen(cost)} vidéos` : 'inconnu';
|
|
64
|
-
// durationRange et aspectRatios arrivent du fetcher (ou fallback)
|
|
65
63
|
const specs = `${m.durationRange ? m.durationRange.join('-') + 's' : '?s'} / ${m.aspectRatios ? m.aspectRatios.length : '?'} ratios`;
|
|
66
|
-
const
|
|
64
|
+
const isCommunity = m.community === true || m.name.includes('/');
|
|
65
|
+
const badge = isCommunity ? '[👥]' : (m.paid_only ? '[💎 Paid]' : '[🌿 Free]');
|
|
67
66
|
videoTable += `| \`${m.name}\` ${badge} | ${m.supportsI2X ? 'T2V/I2V' : 'T2V'} | ${m.output_modalities?.includes('audio') || m.name === 'grok-video' ? '✅' : '❌'} | ${price} | ${specs} |\n`;
|
|
68
67
|
}
|
|
69
68
|
if (!polliGenVideoTool.description.includes('**🎬 Modèles Vidéo Détectés')) {
|
|
@@ -84,7 +83,8 @@ export class ToolRegistryWorker {
|
|
|
84
83
|
for (const m of imageModels.slice(0, 20)) {
|
|
85
84
|
const cost = estimateImageCost(m.name);
|
|
86
85
|
const price = cost ? `${per1pollen(cost)} images` : 'inconnu';
|
|
87
|
-
const
|
|
86
|
+
const isCommunity = m.community === true || m.name.includes('/');
|
|
87
|
+
const badge = isCommunity ? '[👥]' : (m.paid_only ? '[💎 Paid]' : '[🌿 Free]');
|
|
88
88
|
imageTable += `| \`${m.name}\` ${badge} | ${m.supportsI2X ? '✅' : '❌'} | Standard | ${price} |\n`;
|
|
89
89
|
}
|
|
90
90
|
if (imageModels.length > 20) {
|
|
@@ -105,9 +105,9 @@ export class ToolRegistryWorker {
|
|
|
105
105
|
audioTable += `| Modèle | Durée max | Qualité |\n`;
|
|
106
106
|
audioTable += `|--------|-----------|---------|\n`;
|
|
107
107
|
for (const m of audioModels) {
|
|
108
|
-
const
|
|
108
|
+
const isCommunity = m.community === true || m.name.includes('/');
|
|
109
|
+
const badge = isCommunity ? '[👥]' : (m.paid_only ? '[💎 Paid]' : '[🌿 Free]');
|
|
109
110
|
const duration = m.durationRange ? `${m.durationRange.join('-')}s` : 'Standard';
|
|
110
|
-
// STT Whispers or TTS or Music
|
|
111
111
|
audioTable += `| \`${m.name}\` ${badge} | ${duration} | Standard |\n`;
|
|
112
112
|
}
|
|
113
113
|
if (!polliGenAudioTool.description.includes('**🎵 Modèles Audio/Music Détectés')) {
|
|
@@ -138,7 +138,8 @@ export class ToolRegistryWorker {
|
|
|
138
138
|
searchTable += `| Modèle | Description / Specs |\n`;
|
|
139
139
|
searchTable += `|--------|---------------------|\n`;
|
|
140
140
|
for (const m of searchModels) {
|
|
141
|
-
const
|
|
141
|
+
const isCommunity = m.community === true || m.name.includes('/');
|
|
142
|
+
const badge = isCommunity ? '[👥]' : (m.paid_only ? '[💎 Paid]' : '[🌿 Free]');
|
|
142
143
|
// Clean markdown piping conflicts
|
|
143
144
|
let cleanDesc = m.description.replace(/\|/g, '-');
|
|
144
145
|
// Adding "Specialized" hint
|
package/dist/server/proxy.js
CHANGED
|
@@ -446,7 +446,13 @@ export async function handleChatCompletion(req, res, bodyRaw) {
|
|
|
446
446
|
fallbackReason = t('proxy.warnings.quota_unreachable_msg');
|
|
447
447
|
}
|
|
448
448
|
else {
|
|
449
|
-
const
|
|
449
|
+
const effectiveFree = config.questStashInFreeMode !== false
|
|
450
|
+
? quota.tierRemaining + (quota.questStash || 0)
|
|
451
|
+
: quota.tierRemaining;
|
|
452
|
+
const effectiveLimit = config.questStashInFreeMode !== false
|
|
453
|
+
? quota.tierLimit + (quota.questStash || 0)
|
|
454
|
+
: quota.tierLimit;
|
|
455
|
+
const tierRatio = effectiveLimit > 0 ? (effectiveFree / effectiveLimit) : 0;
|
|
450
456
|
if (tierRatio <= (config.thresholds.tier / 100)) {
|
|
451
457
|
log(`[SafetyNet] AlwaysFree Mode: Tier (${(tierRatio * 100).toFixed(1)}%) <= Threshold (${config.thresholds.tier}%). Switching.`);
|
|
452
458
|
emitStatusToast('warning', t('proxy.warnings.tier_limit_title', { threshold: config.thresholds.tier }), 'AlwaysFree Mode');
|
package/dist/server/quota.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export interface QuotaStatus {
|
|
|
3
3
|
tierRemaining: number;
|
|
4
4
|
tierUsed: number;
|
|
5
5
|
tierLimit: number;
|
|
6
|
+
questStash: number;
|
|
6
7
|
walletBalance: number;
|
|
7
8
|
nextResetAt: Date;
|
|
8
9
|
timeUntilReset: number;
|
|
@@ -16,3 +17,8 @@ export interface QuotaStatus {
|
|
|
16
17
|
export declare function fetchUsageForPeriod(apiKey: string, lastReset: Date): Promise<DetailedUsageEntry[]>;
|
|
17
18
|
export declare function getQuotaStatus(forceRefresh?: boolean): Promise<QuotaStatus>;
|
|
18
19
|
export declare function formatQuotaForToast(quota: QuotaStatus): string;
|
|
20
|
+
export declare function fetchQuestStash(apiKey: string): Promise<{
|
|
21
|
+
questStash: number;
|
|
22
|
+
claimedQuestTier: number;
|
|
23
|
+
tierConsumedSinceClaim: number;
|
|
24
|
+
}>;
|
package/dist/server/quota.js
CHANGED
|
@@ -181,6 +181,7 @@ export async function getQuotaStatus(forceRefresh = false) {
|
|
|
181
181
|
tierRemaining: cleanTierRemaining,
|
|
182
182
|
tierUsed,
|
|
183
183
|
tierLimit,
|
|
184
|
+
questStash: 0, // will be computed by fetchQuestStash if needed
|
|
184
185
|
walletBalance: cleanWalletBalance,
|
|
185
186
|
nextResetAt: resetInfo.nextReset,
|
|
186
187
|
timeUntilReset: resetInfo.timeUntilReset,
|
|
@@ -209,6 +210,7 @@ function createDefaultQuota(tierName, limit) {
|
|
|
209
210
|
tierRemaining: 0,
|
|
210
211
|
tierUsed: 0,
|
|
211
212
|
tierLimit: limit,
|
|
213
|
+
questStash: 0,
|
|
212
214
|
walletBalance: 0,
|
|
213
215
|
nextResetAt: new Date(),
|
|
214
216
|
timeUntilReset: 0,
|
|
@@ -302,5 +304,37 @@ export function formatQuotaForToast(quota) {
|
|
|
302
304
|
const hours = Math.floor(ms / (1000 * 60 * 60));
|
|
303
305
|
const minutes = Math.floor((ms % (1000 * 60 * 60)) / (1000 * 60));
|
|
304
306
|
const resetIn = `${hours}h${minutes}m`;
|
|
305
|
-
|
|
307
|
+
const stashStr = quota.questStash > 0
|
|
308
|
+
? ` | 🎁 ~${quota.questStash.toFixed(2)} (stash)`
|
|
309
|
+
: '';
|
|
310
|
+
return `${quota.tierEmoji} ${quota.tierRemaining.toFixed(2)}/${quota.tierLimit} (${tierPercent}%)${stashStr} | 💎 $${quota.walletBalance.toFixed(2)} | ⏰ ${resetIn}`;
|
|
311
|
+
}
|
|
312
|
+
export async function fetchQuestStash(apiKey) {
|
|
313
|
+
let claimedQuestTier = 0;
|
|
314
|
+
let firstClaimMs = Infinity;
|
|
315
|
+
let tierConsumedSinceClaim = 0;
|
|
316
|
+
try {
|
|
317
|
+
const qres = await fetchAPI('/account/quests', apiKey);
|
|
318
|
+
for (const q of (qres?.quests || [])) {
|
|
319
|
+
const r = q.reward;
|
|
320
|
+
if (r && r.claimedAt && r.balanceBucket === 'tier') {
|
|
321
|
+
claimedQuestTier += (r.pollenAmount || 0);
|
|
322
|
+
const cms = new Date(r.claimedAt).getTime();
|
|
323
|
+
if (!isNaN(cms) && cms < firstClaimMs)
|
|
324
|
+
firstClaimMs = cms;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
if (claimedQuestTier > 0 && isFinite(firstClaimMs)) {
|
|
328
|
+
const ures = await fetchAPI('/account/usage?limit=500', apiKey);
|
|
329
|
+
for (const e of (ures?.usage || [])) {
|
|
330
|
+
const ts = new Date(String(e.timestamp).replace(' ', 'T') + (String(e.timestamp).includes('Z') ? '' : 'Z')).getTime();
|
|
331
|
+
if (e.meter_source === 'tier' && !isNaN(ts) && ts >= firstClaimMs) {
|
|
332
|
+
tierConsumedSinceClaim += (e.cost_usd || 0);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
catch { /* fallback gracefully */ }
|
|
338
|
+
const questStash = Math.max(0, claimedQuestTier - tierConsumedSinceClaim);
|
|
339
|
+
return { questStash, claimedQuestTier, tierConsumedSinceClaim };
|
|
306
340
|
}
|
|
@@ -37,7 +37,8 @@ Use 'action=update' to change these. NEVER confuse Chat Mode with Tools Protecti
|
|
|
37
37
|
thresholdsTier: tool.schema.number().optional().describe('Warning threshold PERCENTAGE (e.g. 10 for 10%) for Free Tier.'),
|
|
38
38
|
thresholdsWallet: tool.schema.number().optional().describe('Warning threshold PERCENTAGE (e.g. 50 for 50%) for Wallet balance.'),
|
|
39
39
|
lang: tool.schema.enum(['en', 'fr', 'es', 'de', 'it', 'zh']).optional().describe('Plugin language for commands and toasts (en, fr, es, de, it, zh).'),
|
|
40
|
-
refillOverride: tool.schema.number().optional().describe('Manual Quest Pollen hourly refill override (0.01, 0.15, 0.4, 0.8, or 10). Set to 0 for auto-deduction.')
|
|
40
|
+
refillOverride: tool.schema.number().optional().describe('Manual Quest Pollen hourly refill override (0.01, 0.15, 0.4, 0.8, or 10). Set to 0 for auto-deduction.'),
|
|
41
|
+
questStashInFreeMode: tool.schema.boolean().optional().describe('Count accumulated quest stash as free pollen in alwaysfree Safety Net (default: true).')
|
|
41
42
|
},
|
|
42
43
|
async execute(args, context) {
|
|
43
44
|
if (args.action === 'view') {
|
|
@@ -67,6 +68,8 @@ Use 'action=update' to change these. NEVER confuse Chat Mode with Tools Protecti
|
|
|
67
68
|
if (args.refillOverride !== undefined) {
|
|
68
69
|
updates.refillOverride = args.refillOverride === 0 ? undefined : args.refillOverride;
|
|
69
70
|
}
|
|
71
|
+
if (args.questStashInFreeMode !== undefined)
|
|
72
|
+
updates.questStashInFreeMode = args.questStashInFreeMode;
|
|
70
73
|
if (args.lang !== undefined)
|
|
71
74
|
updates.lang = args.lang;
|
|
72
75
|
if (args.thresholdsTier !== undefined || args.thresholdsWallet !== undefined) {
|
package/package.json
CHANGED