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.
- package/README.de.md +130 -0
- package/README.es.md +130 -0
- package/README.fr.md +130 -0
- package/README.it.md +130 -0
- package/README.md +87 -73
- package/dist/index.js +52 -161
- package/dist/locales/de.json +374 -0
- package/dist/locales/en.json +373 -0
- package/dist/locales/es.json +374 -0
- package/dist/locales/fr.json +373 -0
- package/dist/locales/index.d.ts +1 -0
- package/dist/locales/index.js +37 -0
- package/dist/locales/it.json +374 -0
- package/dist/server/commands.d.ts +6 -0
- package/dist/server/commands.js +394 -125
- package/dist/server/config.d.ts +34 -23
- package/dist/server/config.js +200 -108
- package/dist/server/connect-response.d.ts +2 -0
- package/dist/server/connect-response.js +59 -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 +38 -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 +194 -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 +22 -0
- package/dist/server/models/worker.js +174 -0
- package/dist/server/pollinations-api.d.ts +11 -0
- package/dist/server/pollinations-api.js +21 -8
- package/dist/server/proxy.js +222 -307
- 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 +25 -0
- package/dist/tools/index.js +86 -0
- package/dist/tools/pollinations/beta_discovery.d.ts +9 -0
- package/dist/tools/pollinations/beta_discovery.js +201 -0
- package/dist/tools/pollinations/cost-guard.d.ts +38 -0
- package/dist/tools/pollinations/cost-guard.js +136 -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 +220 -0
- package/dist/tools/pollinations/gen_image.d.ts +11 -0
- package/dist/tools/pollinations/gen_image.js +211 -0
- package/dist/tools/pollinations/gen_music.d.ts +14 -0
- package/dist/tools/pollinations/gen_music.js +157 -0
- package/dist/tools/pollinations/gen_video.d.ts +16 -0
- package/dist/tools/pollinations/gen_video.js +249 -0
- package/dist/tools/pollinations/polli_config.d.ts +2 -0
- package/dist/tools/pollinations/polli_config.js +95 -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 +126 -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 +181 -0
- package/dist/tools/pollinations/shared.js +758 -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 +171 -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 +404 -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 +9 -3
- package/dist/server/models-seed.d.ts +0 -18
- package/dist/server/models-seed.js +0 -55
package/README.md
CHANGED
|
@@ -1,119 +1,133 @@
|
|
|
1
|
-
# 🌸 Pollinations AI Plugin for OpenCode
|
|
1
|
+
# 🌸 Pollinations AI Plugin for OpenCode (v6.2.0)
|
|
2
2
|
|
|
3
3
|
<div align="center">
|
|
4
|
-
<img src="https://avatars.githubusercontent.com/u/88394740?s=400&v=4" alt="Pollinations.ai Logo" width="
|
|
4
|
+
<img src="https://avatars.githubusercontent.com/u/88394740?s=400&v=4" alt="Pollinations.ai Logo" width="200">
|
|
5
5
|
<br>
|
|
6
|
-
<b>The Bridge between OpenCode and the Pollinations.ai Ecosystem
|
|
6
|
+
<b>The Bridge between OpenCode and the Pollinations.ai Ecosystem.</b>
|
|
7
7
|
<br>
|
|
8
|
-
Access
|
|
8
|
+
Access a continuous universe of free basic AI models, or leverage premium enterprise models with our generous Daily Free Tiers directly from your editor.
|
|
9
9
|
</div>
|
|
10
10
|
|
|
11
11
|
<div align="center">
|
|
12
12
|
|
|
13
|
-

|
|
14
14
|

|
|
15
|
-
 | [🛣️ Roadmap](./ROADMAP.md)
|
|
15
|
+

|
|
18
16
|
|
|
19
17
|
</div>
|
|
20
18
|
|
|
21
|
-
|
|
19
|
+
## 📖 Philosophy: Open AI for Creators
|
|
22
20
|
|
|
23
|
-
|
|
21
|
+
> **"No closed doors, no corporate hoops — just good tools and good people."**
|
|
24
22
|
|
|
25
|
-
-
|
|
26
|
-
-
|
|
27
|
-
-
|
|
28
|
-
- **🔐 Secure Auth**: Native OpenCode `/connect` integration
|
|
29
|
-
- **🔄 Hot-Reload**: Change API keys without restarting OpenCode
|
|
23
|
+
Pollinations.ai is an open-source platform created by and for the community. We offer a unified, direct API for generating images, text, audio, and video.
|
|
24
|
+
- **Transparent**: Our code, roadmap, and discussions are public.
|
|
25
|
+
- **Fair Economy**: A single currency (**Pollen**) for all media and models. Predictable and transparent pricing.
|
|
30
26
|
|
|
31
27
|
---
|
|
32
28
|
|
|
33
|
-
##
|
|
29
|
+
## ✨ What's new in V6.2? (The Anti-Hallucination Update)
|
|
30
|
+
- **100% Dynamic Engine**: Hardcoded model lists, default configurations, and fixed prices are gone! In V6.2, OpenCode's AI agent now fetches the latest LLM models, parameters, tags (`[💎 Paid]`, `[🌿 Free]`, limits), and cost approximations dynamically from the Pollinations APIs.
|
|
31
|
+
- **Robust Security**: Protection against path traversal and strict URL verifications are fully integrated.
|
|
32
|
+
- **Improved Web Search**: The `polli_web_search` component maps seamlessly to current web-enabled and specialized groundings options like Google Gemini Fast, Perplexity, and Custom specialized assistants.
|
|
34
33
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
| Tier | Daily Grant | Requirement |
|
|
38
|
-
|:-----|:------------|:------------|
|
|
39
|
-
| 🦠 **Microbe** | 0.1 Pollen | Flagged accounts |
|
|
40
|
-
| 🌱 **Spore** | 1 Pollen | Sign up |
|
|
41
|
-
| 🌿 **Seed** | 3 Pollen | Active GitHub dev (8+ points) |
|
|
42
|
-
| 🌸 **Flower** | 10 Pollen | Published app |
|
|
43
|
-
| 🍯 **Nectar** | 20 Pollen | Major contributor |
|
|
34
|
+
---
|
|
44
35
|
|
|
45
|
-
|
|
36
|
+
## 🧰 Tools & Commands V6.2
|
|
37
|
+
|
|
38
|
+
Beyond text discussion, connecting your key gives OpenCode Agents access to our AI Media Tools powered by Pollinations models:
|
|
39
|
+
|
|
40
|
+
### 💎 Integrated Generative Tools (ENTER ONLY - requires API key)
|
|
41
|
+
- `polli_gen_image` : State-of-the-art imagery models (`Flux`, `Sana`, `Gemini`).
|
|
42
|
+
- `polli_gen_video` : Powerful Text-to-Video and Image-to-Video capabilities (`Wan`, `Veo`, `LTX`, `Reveal`).
|
|
43
|
+
- `polli_gen_audio` & `polli_gen_music` : Magical voice synthesis (ElevenLabs, TTS) and Generative Music.
|
|
44
|
+
- `polli_stt` : High-flying voice transcription (Whisper V3).
|
|
45
|
+
- `polli_web_search` : Connected Web & Specialized Search context (`gemini-search`, `perplexity...`).
|
|
46
|
+
|
|
47
|
+
### 🧰 Free Creator Bonus Tools (Always available)
|
|
48
|
+
- `remove_background` : Built-in ultra-fast image background removal.
|
|
49
|
+
- `gen_qrcode`, `extract_frames`, `extract_audio` : Utilities.
|
|
50
|
+
|
|
51
|
+
### 💻 Complete List of Terminal Commands
|
|
52
|
+
Use the alias **`/poll`** or **`/pollinations`**.
|
|
53
|
+
- `/poll help` : Displays the interactive help table.
|
|
54
|
+
- `/poll connect` : Bring Your Own Key configuration tool (Interactive).
|
|
55
|
+
- `/poll usage full` : Real-time dashboard (Stats), active Freetiers, and Wallet Balance.
|
|
56
|
+
- `/poll config` : Finely adjust Cost Guards, Logs, Language, and Display.
|
|
57
|
+
- `/poll models` : Check the status of available Models.
|
|
58
|
+
- `/poll pricing` : View real-time unified pricing (Average Cost Estimate).
|
|
59
|
+
- `/poll fallback` : Define the ultimate Safety Net Chat model.
|
|
60
|
+
- `/poll mode` : Change mode without going through the API.
|
|
61
|
+
- `/poll infos` : Discover community rules and the leveling system.
|
|
62
|
+
|
|
63
|
+
### 🛡️ The "Cost Guard" & the "Safety Net"
|
|
64
|
+
We have introduced fundamental protections to ensure your workflow never interrupts and your wallet (Wallet or free tiers) is under your control.
|
|
65
|
+
- **Safety Net**: If you use premium models and your daily Pollen quota runs out in the middle of a chat session, the plugin silently and automatically switches to a free model. *No more blocking errors (429).*
|
|
66
|
+
- **Cost Guard for Tools**: OpenCode Agents can be zealous. If an Agent tries to spend too many Pollens to generate a heavy video or music, the plugin intercepts the request. We have implemented an asynchronous flow that asks for your manual confirmation before executing costly generations. You stay in control.
|
|
67
|
+
|
|
68
|
+
### 🌍 Native Multilingual Support (i18n)
|
|
69
|
+
Pollinations for OpenCode natively speaks your language.
|
|
70
|
+
- The Engine Interface, Notifications (Toasts), Tool Returns, and Commands are fully translated into **English (Default)**, **French**, **Spanish**, **German**, and **Italian**.
|
|
71
|
+
- Type `/poll config lang <fr|es|de|it>` in the terminal to switch instantly.
|
|
46
72
|
|
|
47
73
|
---
|
|
48
74
|
|
|
49
|
-
##
|
|
75
|
+
## 🐝 Understanding Pollens & "Free Tiers"
|
|
50
76
|
|
|
51
|
-
|
|
52
|
-
```bash
|
|
53
|
-
npm install -g opencode-pollinations-plugin
|
|
54
|
-
npx opencode-pollinations-plugin
|
|
55
|
-
```
|
|
77
|
+
In the past, Pollinations mainly relied on ad-funded network traffic. Today, running massive models (like Claude 4.5, Flux Pro, Wan Video) costs money. Pollinations therefore introduces the **Enter Universe** which requires an API key and unlocks cutting-edge models.
|
|
56
78
|
|
|
57
|
-
|
|
58
|
-
```
|
|
59
|
-
/connect
|
|
60
|
-
```
|
|
61
|
-
Select **pollinations** → Enter your API key from [enter.pollinations.ai](https://enter.pollinations.ai)
|
|
79
|
+
**But wait, you don't need a credit card!**
|
|
62
80
|
|
|
63
|
-
|
|
64
|
-
Select any `pollinations/*` model in OpenCode and chat!
|
|
81
|
+
**Pollen** is our unified credit system ($1 ≈ 1 Pollen). By connecting a simple Free API Key, you unlock daily Pollen reloads according to your Developer Tier:
|
|
65
82
|
|
|
66
|
-
|
|
83
|
+
| Tier | Daily Reload | Condition |
|
|
84
|
+
| :--- | :--- | :--- |
|
|
85
|
+
| 🦠 **Microbe** | **0.1 Pollen/day** | Just register! |
|
|
86
|
+
| 🍄 **Spore** | **1 Pollen/day** | Automatic verification |
|
|
87
|
+
| 🌱 **Seed** | **3 Pollen/day** | Active GitHub Developer (8+ points) |
|
|
88
|
+
| 🌸 **Flower** | **10 Pollen/day** | **Publish an App** (Like this Plugin!) |
|
|
67
89
|
|
|
68
|
-
|
|
90
|
+
> 🎁 **Get your Free Personal Key (BYOK) on [Pollinations.ai](https://enter.pollinations.ai/authorize?redirect_url=https://github.com/fkom13/opencode-pollinations-plugin) to boost OpenCode!**
|
|
69
91
|
|
|
70
|
-
|
|
92
|
+
*(Note: We still maintain the "Free Universe" fallback for basic chat (`openai-fast`) which requires no key, but its capacity is very limited and mainly designed as a safety net).*
|
|
71
93
|
|
|
72
|
-
|
|
73
|
-
|-------|:------:|:---------:|:-----:|
|
|
74
|
-
| `openai` / `openai-large` | ✅ | - | ✅ |
|
|
75
|
-
| `gemini` / `gemini-search` | ✅ | - | ✅ |
|
|
76
|
-
| `claude` / `claude-large` | ✅ | - | ✅ |
|
|
77
|
-
| `kimi` | ✅ | ✅ | - |
|
|
78
|
-
| `openai-audio` | ✅ | - | ✅ |
|
|
94
|
+
Paid pollens allow you to access even more powerful and premium models.
|
|
79
95
|
|
|
80
|
-
|
|
96
|
+
Daily free tier pollen credits are consumed before touching the wallet (purchased pollen) except for paid models.
|
|
81
97
|
|
|
82
98
|
---
|
|
83
99
|
|
|
84
|
-
##
|
|
100
|
+
## 🚀 Getting Started & Onboarding
|
|
85
101
|
|
|
86
|
-
###
|
|
87
|
-
|
|
88
|
-
- **Gemini**: `gemini`, `gemini-fast`, `gemini-search`, `gemini-large` 💎
|
|
89
|
-
- **Claude**: `claude-fast`, `claude`, `claude-large` 💎
|
|
90
|
-
- **Reasoning**: `deepseek`, `kimi`, `perplexity-reasoning`
|
|
91
|
-
- **Code**: `qwen-coder`, `mistral`
|
|
92
|
-
- **Fast**: `nova-fast`, `grok`
|
|
102
|
+
### 🐧 1. Cross-Platform Configuration (NPM Installation)
|
|
103
|
+
This plugin is **fully cross-platform** (Windows, macOS, Linux) and detects its ports dynamically.
|
|
93
104
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
105
|
+
1. Global installation:
|
|
106
|
+
```bash
|
|
107
|
+
npm install -g opencode-pollinations-plugin
|
|
108
|
+
```
|
|
109
|
+
2. Auto-Configuration:
|
|
110
|
+
```bash
|
|
111
|
+
npx opencode-pollinations-plugin
|
|
112
|
+
```
|
|
113
|
+
*(Or inject it manually into `~/.config/opencode/opencode.json`)*
|
|
97
114
|
|
|
98
|
-
|
|
115
|
+
### 🔑 2. Interactive Onboarding
|
|
116
|
+
Once in OpenCode, simply type the following command in the Agent Terminal:
|
|
117
|
+
```bash
|
|
118
|
+
/poll connect
|
|
119
|
+
```
|
|
120
|
+
An interactive conversational assistant will guide you to inject your Pollinations Key and configure your space. *Restart OpenCode to update the list of models in the UI interface.*
|
|
99
121
|
|
|
100
|
-
## 🔧 Commands
|
|
101
122
|
|
|
102
|
-
```
|
|
103
|
-
/pollinations usage # View Pollen balance
|
|
104
|
-
/pollinations usage full # Detailed model breakdown
|
|
105
|
-
/pollinations status # Plugin health check
|
|
106
|
-
```
|
|
107
123
|
|
|
108
124
|
---
|
|
109
125
|
|
|
110
126
|
## 🔗 Links
|
|
111
127
|
|
|
112
|
-
- **
|
|
113
|
-
- **Discord**: [Join
|
|
114
|
-
- **
|
|
115
|
-
|
|
116
|
-
---
|
|
128
|
+
- **Create your Pollen API Key**: [pollinations.ai](https://pollinations.ai)
|
|
129
|
+
- **Discord Community**: [Join us!](https://discord.gg/pollinations-ai-885844321461485618)
|
|
130
|
+
- **OpenCode Ecosystem**: [opencode.ai](https://opencode.ai/docs/ecosystem#plugins)
|
|
117
131
|
|
|
118
132
|
## 📜 License
|
|
119
133
|
|
package/dist/index.js
CHANGED
|
@@ -1,31 +1,21 @@
|
|
|
1
1
|
import * as http from 'http';
|
|
2
|
-
import * as fs from 'fs';
|
|
3
2
|
import { generatePollinationsConfig } from './server/generate-config.js';
|
|
4
|
-
import { loadConfig,
|
|
3
|
+
import { loadConfig, migrateLegacyConfig } from './server/config.js';
|
|
5
4
|
import { handleChatCompletion } from './server/proxy.js';
|
|
6
|
-
import { createToastHooks, setGlobalClient } from './server/toast.js';
|
|
5
|
+
import { createToastHooks, createToolHooks, setGlobalClient } from './server/toast.js';
|
|
7
6
|
import { createStatusHooks } from './server/status.js';
|
|
8
|
-
import { createCommandHooks } from './server/commands.js';
|
|
7
|
+
import { createCommandHooks, setClientForCommands } from './server/commands.js';
|
|
8
|
+
import { createToolRegistry } from './tools/index.js';
|
|
9
9
|
import { createRequire } from 'module';
|
|
10
10
|
const require = createRequire(import.meta.url);
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
fs.appendFileSync(LOG_FILE, `[${new Date().toISOString()}] ${msg}\n`);
|
|
15
|
-
}
|
|
16
|
-
catch (e) { }
|
|
17
|
-
}
|
|
18
|
-
// === PROXY SERVER (Singleton with Fixed Port) ===
|
|
19
|
-
const DEFAULT_PORT = 18888;
|
|
20
|
-
const GLOBAL_SERVER_KEY = '__POLLINATIONS_PROXY_SERVER__';
|
|
11
|
+
import { log } from './server/logger.js';
|
|
12
|
+
import { ModelRegistry } from './server/models/index.js';
|
|
13
|
+
const sessionModels = new Map();
|
|
21
14
|
const startProxy = () => {
|
|
22
|
-
// Check if server exists in global scope (survives module reloads)
|
|
23
|
-
if (global[GLOBAL_SERVER_KEY]) {
|
|
24
|
-
log(`[Proxy] Reusing existing global server on port ${DEFAULT_PORT}`);
|
|
25
|
-
return Promise.resolve(DEFAULT_PORT);
|
|
26
|
-
}
|
|
27
15
|
return new Promise((resolve) => {
|
|
28
16
|
const server = http.createServer(async (req, res) => {
|
|
17
|
+
// ... (Request Handling) ...
|
|
18
|
+
// We reuse the existing logic structure but simplified startup
|
|
29
19
|
log(`[Proxy] Request: ${req.method} ${req.url}`);
|
|
30
20
|
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
31
21
|
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
|
|
@@ -67,156 +57,58 @@ const startProxy = () => {
|
|
|
67
57
|
res.writeHead(404);
|
|
68
58
|
res.end("Not Found");
|
|
69
59
|
});
|
|
70
|
-
//
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
log(`[Proxy] Port ${port} in use, falling back to dynamic port`);
|
|
82
|
-
server.removeAllListeners('error');
|
|
83
|
-
tryListen(0, false); // Try dynamic port
|
|
84
|
-
}
|
|
85
|
-
else {
|
|
86
|
-
log(`[Proxy] Fatal Error: ${e}`);
|
|
87
|
-
resolve(0);
|
|
88
|
-
}
|
|
89
|
-
});
|
|
90
|
-
};
|
|
91
|
-
tryListen(DEFAULT_PORT, true);
|
|
60
|
+
// Listen on random port (0) to avoid conflicts (CLI/IDE)
|
|
61
|
+
server.listen(0, '127.0.0.1', () => {
|
|
62
|
+
// @ts-ignore
|
|
63
|
+
const assignedPort = server.address().port;
|
|
64
|
+
log(`[Proxy] Started v${require('../package.json').version} (Dynamic Port) on port ${assignedPort}`);
|
|
65
|
+
resolve(assignedPort);
|
|
66
|
+
});
|
|
67
|
+
server.on('error', (e) => {
|
|
68
|
+
log(`[Proxy] Fatal Error: ${e}`);
|
|
69
|
+
resolve(0);
|
|
70
|
+
});
|
|
92
71
|
});
|
|
93
72
|
};
|
|
94
|
-
// === AUTH HOOK: Native /connect Integration ===
|
|
95
|
-
// Auth Hook moved inside plugin to access context
|
|
96
73
|
// === PLUGIN EXPORT ===
|
|
97
74
|
export const PollinationsPlugin = async (ctx) => {
|
|
98
|
-
|
|
99
|
-
|
|
75
|
+
const v = require('../package.json').version;
|
|
76
|
+
log(`Plugin Initializing v${v}...`);
|
|
77
|
+
log(`[ENV] Keys: ${Object.keys(process.env).filter(k => k.includes('OPENCODE') || k.includes('APP') || k.includes('DATA')).join(', ')}`);
|
|
78
|
+
// MIGRATE CONFIG
|
|
79
|
+
migrateLegacyConfig();
|
|
80
|
+
// START PROXY
|
|
100
81
|
const port = await startProxy();
|
|
101
82
|
const localBaseUrl = `http://127.0.0.1:${port}/v1`;
|
|
83
|
+
// INIT MODEL REGISTRY (non-blocking, fire-and-forget)
|
|
84
|
+
ModelRegistry.refresh().then(() => {
|
|
85
|
+
const stats = ModelRegistry.stats();
|
|
86
|
+
log(`[ModelRegistry] Ready: ${stats.image} image, ${stats.video} video, ${stats.audio} audio, ${stats.text} text`);
|
|
87
|
+
// Démarrage du patcher asynchrone des descriptions des Outils (Phase 1.5)
|
|
88
|
+
import('./server/models/worker.js').then(module => {
|
|
89
|
+
module.ToolRegistryWorker.start();
|
|
90
|
+
}).catch(e => log(`[ToolWorker] Failed to load worker: ${e}`));
|
|
91
|
+
}).catch(e => log(`[ModelRegistry] Init failed (will use fallback): ${e}`));
|
|
102
92
|
setGlobalClient(ctx.client);
|
|
93
|
+
setClientForCommands(ctx.client);
|
|
103
94
|
const toastHooks = createToastHooks(ctx.client);
|
|
104
95
|
const commandHooks = createCommandHooks();
|
|
105
|
-
//
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
if (isRefreshing)
|
|
109
|
-
return;
|
|
110
|
-
isRefreshing = true;
|
|
111
|
-
try {
|
|
112
|
-
log('[Event] Refreshing provider config after auth update...');
|
|
113
|
-
const modelsArray = await generatePollinationsConfig();
|
|
114
|
-
const modelsObj = {};
|
|
115
|
-
for (const m of modelsArray) {
|
|
116
|
-
modelsObj[m.id] = m;
|
|
117
|
-
}
|
|
118
|
-
const version = require('../package.json').version;
|
|
119
|
-
// CRITICAL: Fetch current config first to avoid overwriting other providers
|
|
120
|
-
let currentConfig = {};
|
|
121
|
-
try {
|
|
122
|
-
// Try to fetch existing config to preserve other providers
|
|
123
|
-
const response = await ctx.client.fetch('/config');
|
|
124
|
-
if (response.ok) {
|
|
125
|
-
currentConfig = await response.json();
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
catch (err) {
|
|
129
|
-
log(`[Event] Warning: Could not fetch current config: ${err}`);
|
|
130
|
-
}
|
|
131
|
-
// Safe Merge
|
|
132
|
-
if (!currentConfig.provider)
|
|
133
|
-
currentConfig.provider = {};
|
|
134
|
-
currentConfig.provider.pollinations = {
|
|
135
|
-
id: 'openai',
|
|
136
|
-
name: `Pollinations AI (v${version})`,
|
|
137
|
-
options: {
|
|
138
|
-
baseURL: localBaseUrl,
|
|
139
|
-
apiKey: 'plugin-managed',
|
|
140
|
-
},
|
|
141
|
-
models: modelsObj
|
|
142
|
-
};
|
|
143
|
-
// Use Server API to update config with the MERGED object
|
|
144
|
-
await ctx.client.fetch('/config', {
|
|
145
|
-
method: 'PATCH',
|
|
146
|
-
headers: { 'Content-Type': 'application/json' },
|
|
147
|
-
body: JSON.stringify({
|
|
148
|
-
provider: currentConfig.provider
|
|
149
|
-
})
|
|
150
|
-
});
|
|
151
|
-
log(`[Event] Provider config refreshed with ${Object.keys(modelsObj).length} models.`);
|
|
152
|
-
}
|
|
153
|
-
catch (e) {
|
|
154
|
-
log(`[Event] Failed to refresh provider config: ${e}`);
|
|
155
|
-
}
|
|
156
|
-
finally {
|
|
157
|
-
// Debounce: prevent another refresh for 5 seconds
|
|
158
|
-
setTimeout(() => { isRefreshing = false; }, 5000);
|
|
159
|
-
}
|
|
160
|
-
};
|
|
96
|
+
// Build tool registry (conditional on API key presence)
|
|
97
|
+
const toolRegistry = createToolRegistry();
|
|
98
|
+
log(`[Tools] ${Object.keys(toolRegistry).length} tools registered`);
|
|
161
99
|
return {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
log(
|
|
167
|
-
|
|
168
|
-
const authData = await auth();
|
|
169
|
-
if (authData && 'key' in authData) {
|
|
170
|
-
const k = authData.key;
|
|
171
|
-
saveConfig({ apiKey: k });
|
|
172
|
-
return { apiKey: k };
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
catch (e) {
|
|
176
|
-
log(`[AuthHook] loader error: ${e}`);
|
|
177
|
-
}
|
|
178
|
-
const config = loadConfig();
|
|
179
|
-
if (config.apiKey)
|
|
180
|
-
return { apiKey: config.apiKey };
|
|
181
|
-
return {};
|
|
182
|
-
},
|
|
183
|
-
methods: [{
|
|
184
|
-
type: 'api',
|
|
185
|
-
label: 'Pollinations API Key',
|
|
186
|
-
prompts: [{
|
|
187
|
-
type: 'text',
|
|
188
|
-
key: 'apiKey',
|
|
189
|
-
message: 'Enter Pollinations API Key (starts with sk_)',
|
|
190
|
-
validate: (v) => (!v || v.length < 10) ? 'Invalid key' : undefined
|
|
191
|
-
}],
|
|
192
|
-
authorize: async (inputs) => {
|
|
193
|
-
log(`[AuthHook] authorize() called`);
|
|
194
|
-
if (!inputs?.apiKey)
|
|
195
|
-
return { type: 'failed' };
|
|
196
|
-
try {
|
|
197
|
-
const r = await fetch('https://gen.pollinations.ai/text/models', {
|
|
198
|
-
headers: { 'Authorization': `Bearer ${inputs.apiKey}` }
|
|
199
|
-
});
|
|
200
|
-
if (r.ok) {
|
|
201
|
-
log('[AuthHook] Success. Saving & Refreshing Config...');
|
|
202
|
-
saveConfig({ apiKey: inputs.apiKey });
|
|
203
|
-
// CRITICAL: Refresh config IMMEDIATELY after successful auth
|
|
204
|
-
await refreshProviderConfig();
|
|
205
|
-
return { type: 'success', key: inputs.apiKey };
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
catch (e) {
|
|
209
|
-
log(`[AuthHook] Auth error: ${e}`);
|
|
210
|
-
}
|
|
211
|
-
return { type: 'failed' };
|
|
212
|
-
}
|
|
213
|
-
}]
|
|
100
|
+
"chat.message": async (input) => {
|
|
101
|
+
const m = input.model;
|
|
102
|
+
if (m && m.modelID) {
|
|
103
|
+
sessionModels.set(input.sessionID, `${m.providerID}/${m.modelID}`);
|
|
104
|
+
log(`[Hook] Saved active model ${m.providerID}/${m.modelID} for session ${input.sessionID}`);
|
|
105
|
+
}
|
|
214
106
|
},
|
|
215
|
-
|
|
216
|
-
event: async ({ event }) => { },
|
|
107
|
+
tool: toolRegistry,
|
|
217
108
|
async config(config) {
|
|
218
109
|
log("[Hook] config() called");
|
|
219
|
-
//
|
|
110
|
+
// STARTUP only - No complex hot reload logic
|
|
111
|
+
// The user must restart OpenCode to refresh this list if they change keys.
|
|
220
112
|
const modelsArray = await generatePollinationsConfig();
|
|
221
113
|
const modelsObj = {};
|
|
222
114
|
for (const m of modelsArray) {
|
|
@@ -224,19 +116,18 @@ export const PollinationsPlugin = async (ctx) => {
|
|
|
224
116
|
}
|
|
225
117
|
if (!config.provider)
|
|
226
118
|
config.provider = {};
|
|
119
|
+
// Dynamic Provider Name
|
|
227
120
|
const version = require('../package.json').version;
|
|
228
121
|
config.provider['pollinations'] = {
|
|
229
|
-
id: '
|
|
122
|
+
id: 'pollinations',
|
|
230
123
|
name: `Pollinations AI (v${version})`,
|
|
231
|
-
options: {
|
|
232
|
-
baseURL: localBaseUrl,
|
|
233
|
-
apiKey: 'plugin-managed', // Key is managed by auth hook
|
|
234
|
-
},
|
|
124
|
+
options: { baseURL: localBaseUrl },
|
|
235
125
|
models: modelsObj
|
|
236
126
|
};
|
|
237
127
|
log(`[Hook] Registered ${Object.keys(modelsObj).length} models.`);
|
|
238
128
|
},
|
|
239
129
|
...toastHooks,
|
|
130
|
+
...createToolHooks(ctx.client),
|
|
240
131
|
...createStatusHooks(ctx.client),
|
|
241
132
|
...commandHooks
|
|
242
133
|
};
|