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
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="150">
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</b>
6
+ <b>The Bridge between OpenCode and the Pollinations.ai Ecosystem.</b>
7
7
  <br>
8
- Access 25+ AI models with Vision, Reasoning, and Tools support.
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
- ![Version](https://img.shields.io/badge/version-6.0.0--beta.25-blue.svg)
13
+ ![Version](https://img.shields.io/badge/version-v6.2.0-blue.svg)
14
14
  ![License](https://img.shields.io/badge/license-MIT-green.svg)
15
- ![Status](https://img.shields.io/badge/status-Stable-brightgreen.svg)
16
-
17
- [📜 Changelog](./CHANGELOG.md) | [🛣️ Roadmap](./ROADMAP.md)
15
+ ![Status](https://img.shields.io/badge/status-Stable-success.svg)
18
16
 
19
17
  </div>
20
18
 
21
- ---
19
+ ## 📖 Philosophy: Open AI for Creators
22
20
 
23
- ## Features
21
+ > **"No closed doors, no corporate hoops — just good tools and good people."**
24
22
 
25
- - **👁️ Vision Support**: Send images to AI models (OpenAI, Claude, Gemini, Kimi)
26
- - **🧠 Reasoning Models**: Access advanced thinking models (DeepSeek, Kimi, Perplexity)
27
- - **🛠️ Native Tools**: Full function calling support for compatible models
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
- ## 🐝 Understanding Pollen & Tiers
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
- **Pollen** is Pollinations' unified credit system. $1 ≈ 1 Pollen.
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
- > 💡 This plugin was published to the OpenCode ecosystem, granting its author **Flower** tier (10 Pollen/day).
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
- ## 🚀 Quick Start
75
+ ## 🐝 Understanding Pollens & "Free Tiers"
50
76
 
51
- ### 1. Install Plugin
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
- ### 2. Connect Your Account
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
- ### 3. Start Using
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
- ## 👁️ Vision Support
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
- The following models support image input:
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
- | Model | Vision | Reasoning | Tools |
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
- **Usage**: Simply paste an image in the chat or use an image URL. The plugin handles encoding automatically.
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
- ## 📊 Available Models (25+)
100
+ ## 🚀 Getting Started & Onboarding
85
101
 
86
- ### Text/Chat Models
87
- - **OpenAI**: `openai`, `openai-fast`, `openai-large`
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
- ### Paid-Only Models (💎)
95
- These require purchased credits (not daily grants):
96
- - `claude-large`, `gemini-large`, `veo`, `seedream-pro`
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
- - **Get API Key**: [enter.pollinations.ai](https://enter.pollinations.ai)
113
- - **Discord**: [Join Community](https://discord.gg/pollinations-ai-885844321461485618)
114
- - **GitHub**: [Plugin Repository](https://github.com/fkom13/opencode-pollinations-plugin)
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, saveConfig } from './server/config.js';
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
- const LOG_FILE = '/tmp/opencode_pollinations_v4.log';
12
- function log(msg) {
13
- try {
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
- // Try fixed port first, fallback to dynamic if occupied
71
- const tryListen = (port, fallbackToDynamic) => {
72
- server.listen(port, '127.0.0.1', () => {
73
- // @ts-ignore
74
- const assignedPort = server.address().port;
75
- global[GLOBAL_SERVER_KEY] = server;
76
- log(`[Proxy] Started v${require('../package.json').version} on port ${assignedPort}${port === 0 ? ' (dynamic fallback)' : ''}`);
77
- resolve(assignedPort);
78
- });
79
- server.on('error', (e) => {
80
- if (e.code === 'EADDRINUSE' && fallbackToDynamic) {
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
- log(`Plugin Initializing v${require('../package.json').version}...`);
99
- // START PROXY on fixed port
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
- // Helper: Refresh provider config (for hot-reload after /connect)
106
- let isRefreshing = false;
107
- const refreshProviderConfig = async () => {
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
- // AUTH HOOK: Native /connect integration (INLINED)
163
- auth: {
164
- provider: 'pollinations',
165
- loader: async (auth, provider) => {
166
- log('[AuthHook] loader() called');
167
- try {
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
- // Event hook removed (logic moved to authorize)
216
- event: async ({ event }) => { },
107
+ tool: toolRegistry,
217
108
  async config(config) {
218
109
  log("[Hook] config() called");
219
- // Generate models based on current auth state
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: 'openai',
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
  };