opencode-pollinations-plugin 6.0.0-beta.23 → 6.0.0-beta.25

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 (2) hide show
  1. package/dist/index.js +80 -98
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -92,80 +92,7 @@ const startProxy = () => {
92
92
  });
93
93
  };
94
94
  // === AUTH HOOK: Native /connect Integration ===
95
- const createAuthHook = () => ({
96
- provider: 'pollinations',
97
- // LOADER: Called by OpenCode when it needs credentials
98
- // This enables HOT RELOAD - called before each request that needs auth
99
- loader: async (auth, provider) => {
100
- log('[AuthHook] loader() called - fetching credentials');
101
- try {
102
- const authData = await auth();
103
- if (authData && 'key' in authData && authData.key) {
104
- log(`[AuthHook] Got key from OpenCode auth: ${authData.key.substring(0, 8)}...`);
105
- // Sync to our config for other parts of the plugin
106
- saveConfig({ apiKey: authData.key });
107
- return { apiKey: authData.key };
108
- }
109
- }
110
- catch (e) {
111
- log(`[AuthHook] loader() error: ${e}`);
112
- }
113
- // Fallback to our own config
114
- const config = loadConfig();
115
- if (config.apiKey) {
116
- log(`[AuthHook] Using key from plugin config: ${config.apiKey.substring(0, 8)}...`);
117
- return { apiKey: config.apiKey };
118
- }
119
- log('[AuthHook] No API key available');
120
- return {};
121
- },
122
- // METHODS: Define how user can authenticate
123
- methods: [{
124
- type: 'api',
125
- label: 'API Key',
126
- prompts: [{
127
- type: 'text',
128
- key: 'apiKey',
129
- message: 'Enter your Pollinations API Key',
130
- placeholder: 'sk_...',
131
- validate: (value) => {
132
- if (!value || value.length < 10) {
133
- return 'API key must be at least 10 characters';
134
- }
135
- if (!value.startsWith('sk_') && !value.startsWith('sk-')) {
136
- return 'API key should start with sk_ or sk-';
137
- }
138
- return undefined; // Valid
139
- }
140
- }],
141
- authorize: async (inputs) => {
142
- log(`[AuthHook] authorize() called with key: ${inputs?.apiKey?.substring(0, 8)}...`);
143
- if (!inputs?.apiKey) {
144
- return { type: 'failed' };
145
- }
146
- // Validate key by testing API
147
- try {
148
- const response = await fetch('https://gen.pollinations.ai/text/models', {
149
- headers: { 'Authorization': `Bearer ${inputs.apiKey}` }
150
- });
151
- if (response.ok) {
152
- log('[AuthHook] Key validated successfully');
153
- // Save to our config for immediate use
154
- saveConfig({ apiKey: inputs.apiKey });
155
- return { type: 'success', key: inputs.apiKey };
156
- }
157
- else {
158
- log(`[AuthHook] Key validation failed: ${response.status}`);
159
- return { type: 'failed' };
160
- }
161
- }
162
- catch (e) {
163
- log(`[AuthHook] Key validation error: ${e}`);
164
- return { type: 'failed' };
165
- }
166
- }
167
- }]
168
- });
95
+ // Auth Hook moved inside plugin to access context
169
96
  // === PLUGIN EXPORT ===
170
97
  export const PollinationsPlugin = async (ctx) => {
171
98
  log(`Plugin Initializing v${require('../package.json').version}...`);
@@ -189,22 +116,36 @@ export const PollinationsPlugin = async (ctx) => {
189
116
  modelsObj[m.id] = m;
190
117
  }
191
118
  const version = require('../package.json').version;
192
- // Use Server API to PATCH the config at runtime
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
193
144
  await ctx.client.fetch('/config', {
194
145
  method: 'PATCH',
195
146
  headers: { 'Content-Type': 'application/json' },
196
147
  body: JSON.stringify({
197
- provider: {
198
- pollinations: {
199
- id: 'openai',
200
- name: `Pollinations AI (v${version})`,
201
- options: {
202
- baseURL: localBaseUrl,
203
- apiKey: 'plugin-managed',
204
- },
205
- models: modelsObj
206
- }
207
- }
148
+ provider: currentConfig.provider
208
149
  })
209
150
  });
210
151
  log(`[Event] Provider config refreshed with ${Object.keys(modelsObj).length} models.`);
@@ -218,20 +159,61 @@ export const PollinationsPlugin = async (ctx) => {
218
159
  }
219
160
  };
220
161
  return {
221
- // AUTH HOOK: Native /connect integration
222
- auth: createAuthHook(),
223
- // EVENT HOOK: Listen ONLY for explicit /connect command
224
- // We removed installation.updated/server.connected because they caused infinite loops
225
- event: async ({ event }) => {
226
- if (event.type === 'tui.command.execute') {
227
- const cmd = event.command || event.data?.command;
228
- if (cmd === 'connect' || cmd === '/connect') {
229
- log('[Event] /connect command detected - will refresh after auth hook completes');
230
- // Small delay to let auth hook complete
231
- setTimeout(() => refreshProviderConfig(), 2000);
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
+ }
232
174
  }
233
- }
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
+ }]
234
214
  },
215
+ // Event hook removed (logic moved to authorize)
216
+ event: async ({ event }) => { },
235
217
  async config(config) {
236
218
  log("[Hook] config() called");
237
219
  // Generate models based on current auth state
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "opencode-pollinations-plugin",
3
3
  "displayName": "Pollinations AI (V5.6)",
4
- "version": "6.0.0-beta.23",
4
+ "version": "6.0.0-beta.25",
5
5
  "description": "Native Pollinations.ai Provider Plugin for OpenCode",
6
6
  "publisher": "pollinations",
7
7
  "repository": {