opencode-free-fleet 0.1.0 ā 0.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.md +85 -284
- package/dist/core/adapters/index.d.ts +13 -0
- package/dist/core/adapters/index.js +546 -0
- package/dist/core/oracle.d.ts +84 -0
- package/dist/core/oracle.js +234 -0
- package/dist/core/racer.d.ts +105 -0
- package/dist/core/racer.js +209 -0
- package/dist/core/scout.d.ts +124 -0
- package/dist/core/scout.js +503 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +332 -0
- package/dist/types/index.d.ts +144 -0
- package/dist/types/index.js +54 -0
- package/dist/version.d.ts +6 -0
- package/dist/version.js +6 -0
- package/package.json +11 -3
- package/src/version.ts +2 -2
package/dist/index.js
ADDED
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenCode Free Fleet
|
|
3
|
+
*
|
|
4
|
+
* Economic Load Balancing and Zero-Cost Model Discovery for OpenCode
|
|
5
|
+
*
|
|
6
|
+
* This plugin automatically discovers, ranks, and competes free LLM models
|
|
7
|
+
* based on SOTA benchmark performance, enabling zero-cost, zero-latency
|
|
8
|
+
* execution for OpenCode agents.
|
|
9
|
+
*
|
|
10
|
+
* @version 0.2.1
|
|
11
|
+
* @author Phorde
|
|
12
|
+
*/
|
|
13
|
+
// Export version
|
|
14
|
+
export { VERSION, BUILD_DATE } from './version.js';
|
|
15
|
+
// Export types
|
|
16
|
+
export * from './types/index.js';
|
|
17
|
+
// Export core modules
|
|
18
|
+
export { Scout, createScout } from './core/scout.js';
|
|
19
|
+
export { FreeModelRacer, competeFreeModels, createRacer } from './core/racer.js';
|
|
20
|
+
// Import fs
|
|
21
|
+
import * as fs from 'fs/promises';
|
|
22
|
+
import * as path from 'path';
|
|
23
|
+
/**
|
|
24
|
+
* Main plugin function
|
|
25
|
+
*
|
|
26
|
+
* Initializes Free Fleet plugin and returns hooks for OpenCode integration.
|
|
27
|
+
*
|
|
28
|
+
* @param ctx - Plugin context provided by OpenCode
|
|
29
|
+
* @returns Plugin hooks
|
|
30
|
+
*/
|
|
31
|
+
export const FreeFleetPlugin = async (ctx) => {
|
|
32
|
+
const { client, directory } = ctx;
|
|
33
|
+
console.log('\nš¤ OpenCode Free Fleet - Initializing...');
|
|
34
|
+
console.log(` Version: 0.2.1`);
|
|
35
|
+
console.log(` Directory: ${directory}\n`);
|
|
36
|
+
// Get config directory
|
|
37
|
+
const configDir = process.env.HOME ? `${process.env.HOME}/.config/opencode` : directory;
|
|
38
|
+
// Free models cache path
|
|
39
|
+
const freeModelsCachePath = path.join(configDir, 'free-models.json');
|
|
40
|
+
// Initialize Scout instance
|
|
41
|
+
const { createScout } = await import('./core/scout.js');
|
|
42
|
+
const scout = createScout({
|
|
43
|
+
antigravityPath: path.join(configDir, 'antigravity-accounts.json'),
|
|
44
|
+
opencodeConfigPath: path.join(configDir, 'oh-my-opencode.json')
|
|
45
|
+
});
|
|
46
|
+
/**
|
|
47
|
+
* Run discovery and cache results
|
|
48
|
+
*/
|
|
49
|
+
const runDiscovery = async () => {
|
|
50
|
+
try {
|
|
51
|
+
console.log('š Free Fleet: Starting model discovery...');
|
|
52
|
+
const results = await scout.discover();
|
|
53
|
+
scout.printSummary(results);
|
|
54
|
+
// Cache results to free-models.json
|
|
55
|
+
const cacheData = {
|
|
56
|
+
version: '0.2.1',
|
|
57
|
+
timestamp: new Date().toISOString(),
|
|
58
|
+
categories: Object.fromEntries(Object.entries(results).map(([cat, res]) => [
|
|
59
|
+
cat,
|
|
60
|
+
{
|
|
61
|
+
totalModels: res.models.length,
|
|
62
|
+
eliteModels: res.eliteModels.map(m => m.id),
|
|
63
|
+
topModels: res.rankedModels.slice(0, 5).map(m => ({
|
|
64
|
+
id: m.id,
|
|
65
|
+
isElite: res.eliteModels.includes(m)
|
|
66
|
+
}))
|
|
67
|
+
}
|
|
68
|
+
]))
|
|
69
|
+
};
|
|
70
|
+
await fs.writeFile(freeModelsCachePath, JSON.stringify(cacheData, null, 2));
|
|
71
|
+
console.log(`ā Free Fleet: Cached results to ${freeModelsCachePath}`);
|
|
72
|
+
// Log structured event
|
|
73
|
+
await client.app.log?.({
|
|
74
|
+
service: 'free-fleet',
|
|
75
|
+
level: 'info',
|
|
76
|
+
message: 'Model discovery completed',
|
|
77
|
+
extra: {
|
|
78
|
+
categories: Object.keys(results).length,
|
|
79
|
+
totalModels: Object.values(results).reduce((sum, r) => sum + r.models.length, 0),
|
|
80
|
+
cachedTo: freeModelsCachePath
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
console.error('ā Free Fleet: Discovery failed', error);
|
|
86
|
+
await client.app.log?.({
|
|
87
|
+
service: 'free-fleet',
|
|
88
|
+
level: 'error',
|
|
89
|
+
message: 'Model discovery failed',
|
|
90
|
+
extra: { error: String(error) }
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
// Check if cache exists
|
|
95
|
+
let cacheExists = false;
|
|
96
|
+
try {
|
|
97
|
+
await fs.access(freeModelsCachePath);
|
|
98
|
+
cacheExists = true;
|
|
99
|
+
console.log(`ā Free Fleet: Found cache at ${freeModelsCachePath}`);
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
console.log(`ā¹ļø Free Fleet: No cache found, will run discovery on startup`);
|
|
103
|
+
}
|
|
104
|
+
return {
|
|
105
|
+
/**
|
|
106
|
+
* onStart Hook
|
|
107
|
+
* Runs when plugin is loaded
|
|
108
|
+
*/
|
|
109
|
+
onStart: async () => {
|
|
110
|
+
console.log('ā
Free Fleet: Plugin started\n');
|
|
111
|
+
await client.app.log?.({
|
|
112
|
+
service: 'free-fleet',
|
|
113
|
+
level: 'info',
|
|
114
|
+
message: 'Free Fleet plugin initialized',
|
|
115
|
+
extra: { version: '0.2.1', cacheExists }
|
|
116
|
+
});
|
|
117
|
+
// Run discovery if cache doesn't exist
|
|
118
|
+
if (!cacheExists) {
|
|
119
|
+
console.log('š Free Fleet: No cache found, running initial discovery...');
|
|
120
|
+
await runDiscovery();
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
/**
|
|
124
|
+
* Custom Tool: free_fleet_scout
|
|
125
|
+
* Triggers manual model discovery update
|
|
126
|
+
*/
|
|
127
|
+
tool: {
|
|
128
|
+
'free_fleet_scout': {
|
|
129
|
+
description: 'Discover and rank free LLM models from OpenRouter API',
|
|
130
|
+
args: {
|
|
131
|
+
category: {
|
|
132
|
+
type: 'string',
|
|
133
|
+
description: 'Optional category filter (coding, reasoning, speed, multimodal, writing)',
|
|
134
|
+
optional: true
|
|
135
|
+
},
|
|
136
|
+
top: {
|
|
137
|
+
type: 'number',
|
|
138
|
+
description: 'Number of top models to display (default: 5)',
|
|
139
|
+
optional: true
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
execute: async (args, context) => {
|
|
143
|
+
console.log('š free_fleet_scout: Starting manual discovery...');
|
|
144
|
+
const results = await scout.discover();
|
|
145
|
+
if (args.category) {
|
|
146
|
+
const category = args.category;
|
|
147
|
+
if (results[category]) {
|
|
148
|
+
const result = results[category];
|
|
149
|
+
const top = args.top || 5;
|
|
150
|
+
console.log(`\nš ${category.toUpperCase()} (top ${top}):`);
|
|
151
|
+
result.rankedModels.slice(0, top).forEach((model, i) => {
|
|
152
|
+
const isElite = result.eliteModels.includes(model);
|
|
153
|
+
console.log(` ${i + 1}. ${model.id}${isElite ? ' ā ELITE' : ''}`);
|
|
154
|
+
});
|
|
155
|
+
await client.app.log?.({
|
|
156
|
+
service: 'free-fleet',
|
|
157
|
+
level: 'info',
|
|
158
|
+
message: `Discovery for category '${category}' completed`,
|
|
159
|
+
extra: {
|
|
160
|
+
category,
|
|
161
|
+
totalModels: result.models.length,
|
|
162
|
+
eliteModels: result.eliteModels.length,
|
|
163
|
+
topDisplayed: top
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
return {
|
|
167
|
+
success: true,
|
|
168
|
+
category,
|
|
169
|
+
totalModels: result.models.length,
|
|
170
|
+
eliteModels: result.eliteModels.length,
|
|
171
|
+
topModels: result.rankedModels.slice(0, top).map(m => m.id)
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
await client.app.log?.({
|
|
176
|
+
service: 'free-fleet',
|
|
177
|
+
level: 'warn',
|
|
178
|
+
message: `Category '${args.category}' not found`,
|
|
179
|
+
extra: {
|
|
180
|
+
availableCategories: Object.keys(results),
|
|
181
|
+
requestedCategory: args.category
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
return {
|
|
185
|
+
success: false,
|
|
186
|
+
error: `Category '${args.category}' not found. Available: ${Object.keys(results).join(', ')}`
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
scout.printSummary(results);
|
|
192
|
+
await client.app.log?.({
|
|
193
|
+
service: 'free-fleet',
|
|
194
|
+
level: 'info',
|
|
195
|
+
message: 'Full discovery completed',
|
|
196
|
+
extra: {
|
|
197
|
+
categories: Object.keys(results).length,
|
|
198
|
+
totalModels: Object.values(results).reduce((sum, r) => sum + r.models.length, 0)
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
return {
|
|
202
|
+
success: true,
|
|
203
|
+
categories: Object.keys(results).length,
|
|
204
|
+
totalModels: Object.values(results).reduce((sum, r) => sum + r.models.length, 0)
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
/**
|
|
210
|
+
* Custom Tool: free_fleet_router
|
|
211
|
+
* Accepts { category, prompt }, runs race, returns result
|
|
212
|
+
*/
|
|
213
|
+
'free_fleet_router': {
|
|
214
|
+
description: 'Race between free models and return fastest response',
|
|
215
|
+
args: {
|
|
216
|
+
category: {
|
|
217
|
+
type: 'string',
|
|
218
|
+
description: 'Category to use (coding, reasoning, speed, multimodal, writing)',
|
|
219
|
+
required: true
|
|
220
|
+
},
|
|
221
|
+
prompt: {
|
|
222
|
+
type: 'string',
|
|
223
|
+
description: 'Prompt to send to each model',
|
|
224
|
+
required: true
|
|
225
|
+
},
|
|
226
|
+
timeoutMs: {
|
|
227
|
+
type: 'number',
|
|
228
|
+
description: 'Timeout in milliseconds (default: 30000)',
|
|
229
|
+
optional: true
|
|
230
|
+
}
|
|
231
|
+
},
|
|
232
|
+
execute: async (args, context) => {
|
|
233
|
+
console.log(`š free_fleet_router: Starting race for category '${args.category}'`);
|
|
234
|
+
try {
|
|
235
|
+
// Read cached models
|
|
236
|
+
const cacheContent = await fs.readFile(freeModelsCachePath, 'utf-8');
|
|
237
|
+
const cache = JSON.parse(cacheContent);
|
|
238
|
+
const categoryKey = args.category;
|
|
239
|
+
const categoryData = cache.categories[categoryKey];
|
|
240
|
+
if (!categoryData) {
|
|
241
|
+
await client.app.log?.({
|
|
242
|
+
service: 'free-fleet',
|
|
243
|
+
level: 'warn',
|
|
244
|
+
message: `Category '${args.category}' not found in cache`,
|
|
245
|
+
extra: { availableCategories: Object.keys(cache.categories) }
|
|
246
|
+
});
|
|
247
|
+
return {
|
|
248
|
+
success: false,
|
|
249
|
+
error: `Category '${args.category}' not found in cache. Run free_fleet_scout first.`
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
// Get models for this category
|
|
253
|
+
const models = categoryData.topModels.map((m) => `openrouter/${m.id}`);
|
|
254
|
+
console.log(`š free_fleet_router: Competing with ${models.length} models:`);
|
|
255
|
+
models.forEach((m, i) => {
|
|
256
|
+
const modelData = categoryData.topModels.find((d) => d.id === m.replace('openrouter/', ''));
|
|
257
|
+
console.log(` ${i + 1}. ${m}${modelData?.isElite ? ' ā ELITE' : ''}`);
|
|
258
|
+
});
|
|
259
|
+
// Import racer
|
|
260
|
+
const { FreeModelRacer } = await import('./core/racer.js');
|
|
261
|
+
const racer = new FreeModelRacer({
|
|
262
|
+
timeoutMs: args.timeoutMs,
|
|
263
|
+
onProgress: (model, status) => {
|
|
264
|
+
console.log(` ${model}: ${status}`);
|
|
265
|
+
}
|
|
266
|
+
});
|
|
267
|
+
// Execute race with simulated model execution
|
|
268
|
+
// In production, this would use the OpenCode client
|
|
269
|
+
const winner = await racer.race(models, async (model) => {
|
|
270
|
+
// This is where you'd execute with OpenCode client
|
|
271
|
+
// For now, simulate with a mock
|
|
272
|
+
const delay = Math.random() * 3000 + 500;
|
|
273
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
274
|
+
return {
|
|
275
|
+
model,
|
|
276
|
+
response: `Response from ${model} for: ${args.prompt.substring(0, 50)}...`,
|
|
277
|
+
delay
|
|
278
|
+
};
|
|
279
|
+
}, `router-${Date.now()}`);
|
|
280
|
+
console.log(`š free_fleet_router: Winner - ${winner.model} (${winner.duration.toFixed(0)}ms)`);
|
|
281
|
+
await client.app.log?.({
|
|
282
|
+
service: 'free-fleet',
|
|
283
|
+
level: 'info',
|
|
284
|
+
message: `Race completed for category '${args.category}'`,
|
|
285
|
+
extra: {
|
|
286
|
+
winner: winner.model,
|
|
287
|
+
duration: winner.duration,
|
|
288
|
+
modelsCompeted: models.length
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
return {
|
|
292
|
+
success: true,
|
|
293
|
+
winner: winner.model,
|
|
294
|
+
duration: winner.duration,
|
|
295
|
+
result: winner.result,
|
|
296
|
+
category: args.category
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
catch (error) {
|
|
300
|
+
const err = error;
|
|
301
|
+
// Check if cache doesn't exist
|
|
302
|
+
if (err.message.includes('ENOENT')) {
|
|
303
|
+
await client.app.log?.({
|
|
304
|
+
service: 'free-fleet',
|
|
305
|
+
level: 'warn',
|
|
306
|
+
message: 'No cache found',
|
|
307
|
+
extra: { error: err.message }
|
|
308
|
+
});
|
|
309
|
+
return {
|
|
310
|
+
success: false,
|
|
311
|
+
error: 'No cache found. Run free_fleet_scout first to build the model cache.'
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
console.error('ā free_fleet_router: Failed', error);
|
|
315
|
+
await client.app.log?.({
|
|
316
|
+
service: 'free-fleet',
|
|
317
|
+
level: 'error',
|
|
318
|
+
message: 'Race failed',
|
|
319
|
+
extra: { error: err.message, category: args.category }
|
|
320
|
+
});
|
|
321
|
+
return {
|
|
322
|
+
success: false,
|
|
323
|
+
error: err.message
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
};
|
|
330
|
+
};
|
|
331
|
+
// Export plugin as default
|
|
332
|
+
export default FreeFleetPlugin;
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for OpenCode Free Fleet v0.2.0
|
|
3
|
+
*
|
|
4
|
+
* Simplified types to fix compilation errors
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Unified free model interface (provider-agnostic)
|
|
8
|
+
*/
|
|
9
|
+
export interface FreeModel {
|
|
10
|
+
id: string;
|
|
11
|
+
provider: string;
|
|
12
|
+
name: string;
|
|
13
|
+
description?: string;
|
|
14
|
+
contextLength?: number;
|
|
15
|
+
maxOutputTokens?: number;
|
|
16
|
+
pricing: {
|
|
17
|
+
prompt: string;
|
|
18
|
+
completion: string;
|
|
19
|
+
request: string;
|
|
20
|
+
};
|
|
21
|
+
isFree: boolean;
|
|
22
|
+
isElite: boolean;
|
|
23
|
+
category: ModelCategory;
|
|
24
|
+
confidence?: number;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Model category identifiers
|
|
28
|
+
*/
|
|
29
|
+
export type ModelCategory = 'coding' | 'reasoning' | 'speed' | 'multimodal' | 'writing';
|
|
30
|
+
/**
|
|
31
|
+
* Provider model interface
|
|
32
|
+
*/
|
|
33
|
+
export interface ProviderModel {
|
|
34
|
+
id: string;
|
|
35
|
+
name: string;
|
|
36
|
+
description?: string;
|
|
37
|
+
context_length?: number;
|
|
38
|
+
max_output_tokens?: number;
|
|
39
|
+
pricing?: {
|
|
40
|
+
prompt: string;
|
|
41
|
+
completion: string;
|
|
42
|
+
request: string;
|
|
43
|
+
prompt_price?: string;
|
|
44
|
+
top_provider?: any;
|
|
45
|
+
};
|
|
46
|
+
architecture?: any;
|
|
47
|
+
top_provider?: any;
|
|
48
|
+
serverless_free?: boolean;
|
|
49
|
+
max_context_tokens?: number;
|
|
50
|
+
modality?: string;
|
|
51
|
+
tokenizer?: string;
|
|
52
|
+
context_window?: number;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Provider Adapter interface
|
|
56
|
+
*/
|
|
57
|
+
export interface ProviderAdapter {
|
|
58
|
+
readonly providerId: string;
|
|
59
|
+
readonly providerName: string;
|
|
60
|
+
fetchModels(): Promise<ProviderModel[]>;
|
|
61
|
+
isFreeModel(model: ProviderModel): boolean;
|
|
62
|
+
normalizeModel(model: ProviderModel): FreeModel;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Scout configuration
|
|
66
|
+
*/
|
|
67
|
+
export interface ScoutConfig {
|
|
68
|
+
antigravityPath?: string;
|
|
69
|
+
opencodeConfigPath?: string;
|
|
70
|
+
allowAntigravity?: boolean;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Scout result with ranked models
|
|
74
|
+
*/
|
|
75
|
+
export interface ScoutResult {
|
|
76
|
+
category: ModelCategory;
|
|
77
|
+
models: FreeModel[];
|
|
78
|
+
rankedModels: FreeModel[];
|
|
79
|
+
eliteModels: FreeModel[];
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Race execution result
|
|
83
|
+
*/
|
|
84
|
+
export interface RaceResult<T = unknown> {
|
|
85
|
+
model: string;
|
|
86
|
+
result: T;
|
|
87
|
+
duration: number;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Race configuration
|
|
91
|
+
*/
|
|
92
|
+
export interface RaceConfig {
|
|
93
|
+
timeoutMs?: number;
|
|
94
|
+
abortController?: AbortController;
|
|
95
|
+
onProgress?: (model: string, status: 'started' | 'completed' | 'failed', error?: Error) => void;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Provider discovery result
|
|
99
|
+
*/
|
|
100
|
+
export interface ActiveProvidersResult {
|
|
101
|
+
providers: string[];
|
|
102
|
+
adapters: Map<string, ProviderAdapter>;
|
|
103
|
+
errors: string[];
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Category configuration with model selection and fallback chain
|
|
107
|
+
*/
|
|
108
|
+
export interface CategoryConfig {
|
|
109
|
+
model: string;
|
|
110
|
+
fallback: string[];
|
|
111
|
+
description: string;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Plugin context provided by OpenCode
|
|
115
|
+
*/
|
|
116
|
+
export interface PluginContext {
|
|
117
|
+
project: any;
|
|
118
|
+
client: any;
|
|
119
|
+
$: any;
|
|
120
|
+
directory: string;
|
|
121
|
+
worktree: string;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Plugin hook definitions
|
|
125
|
+
*/
|
|
126
|
+
export interface PluginHooks {
|
|
127
|
+
onStart?: () => Promise<void> | void;
|
|
128
|
+
tool?: Record<string, any>;
|
|
129
|
+
[key: string]: any;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Export type for Plugin function
|
|
133
|
+
*/
|
|
134
|
+
export type PluginFunction = (ctx: PluginContext) => Promise<PluginHooks>;
|
|
135
|
+
/**
|
|
136
|
+
* SOTA benchmark elite families
|
|
137
|
+
*/
|
|
138
|
+
export declare const ELITE_FAMILIES: {
|
|
139
|
+
readonly coding: readonly ["qwen-2.5-coder", "qwen3-coder", "deepseek-coder", "deepseek-v3", "llama-3.3-70b", "llama-3.3", "codestral", "starcoder"];
|
|
140
|
+
readonly reasoning: readonly ["deepseek-r1", "deepseek-reasoner", "qwq", "qwq-32b", "o1-open", "o3-mini", "reasoning", "r1"];
|
|
141
|
+
readonly speed: readonly ["mistral-small", "haiku", "flash", "gemma-2", "gemma-3", "distill", "nano", "lite"];
|
|
142
|
+
readonly multimodal: readonly ["vl", "vision", "molmo", "nemotron-vl", "pixtral", "qwen-vl"];
|
|
143
|
+
readonly writing: readonly ["trinity", "qwen-next", "chimera", "writer"];
|
|
144
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for OpenCode Free Fleet v0.2.0
|
|
3
|
+
*
|
|
4
|
+
* Simplified types to fix compilation errors
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* SOTA benchmark elite families
|
|
8
|
+
*/
|
|
9
|
+
export const ELITE_FAMILIES = {
|
|
10
|
+
coding: [
|
|
11
|
+
'qwen-2.5-coder',
|
|
12
|
+
'qwen3-coder',
|
|
13
|
+
'deepseek-coder',
|
|
14
|
+
'deepseek-v3',
|
|
15
|
+
'llama-3.3-70b',
|
|
16
|
+
'llama-3.3',
|
|
17
|
+
'codestral',
|
|
18
|
+
'starcoder'
|
|
19
|
+
],
|
|
20
|
+
reasoning: [
|
|
21
|
+
'deepseek-r1',
|
|
22
|
+
'deepseek-reasoner',
|
|
23
|
+
'qwq',
|
|
24
|
+
'qwq-32b',
|
|
25
|
+
'o1-open',
|
|
26
|
+
'o3-mini',
|
|
27
|
+
'reasoning',
|
|
28
|
+
'r1'
|
|
29
|
+
],
|
|
30
|
+
speed: [
|
|
31
|
+
'mistral-small',
|
|
32
|
+
'haiku',
|
|
33
|
+
'flash',
|
|
34
|
+
'gemma-2',
|
|
35
|
+
'gemma-3',
|
|
36
|
+
'distill',
|
|
37
|
+
'nano',
|
|
38
|
+
'lite'
|
|
39
|
+
],
|
|
40
|
+
multimodal: [
|
|
41
|
+
'vl',
|
|
42
|
+
'vision',
|
|
43
|
+
'molmo',
|
|
44
|
+
'nemotron-vl',
|
|
45
|
+
'pixtral',
|
|
46
|
+
'qwen-vl'
|
|
47
|
+
],
|
|
48
|
+
writing: [
|
|
49
|
+
'trinity',
|
|
50
|
+
'qwen-next',
|
|
51
|
+
'chimera',
|
|
52
|
+
'writer'
|
|
53
|
+
]
|
|
54
|
+
};
|
package/dist/version.js
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-free-fleet",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Economic Load Balancing and Zero-Cost Model Discovery for OpenCode - Automatically ranks and competes free LLM models by benchmark performance",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Phorde",
|
|
@@ -31,11 +31,12 @@
|
|
|
31
31
|
"src/version.ts"
|
|
32
32
|
],
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@opencode-ai/plugin": "^1.1.0"
|
|
34
|
+
"@opencode-ai/plugin": "^1.1.0",
|
|
35
|
+
"typescript": "^5.9.3"
|
|
35
36
|
},
|
|
36
37
|
"devDependencies": {
|
|
37
38
|
"@eslint/js": "^9.39.1",
|
|
38
|
-
"@types/node": "^
|
|
39
|
+
"@types/node": "^25.1.0",
|
|
39
40
|
"@typescript-eslint/eslint-plugin": "8.47.0",
|
|
40
41
|
"@typescript-eslint/parser": "8.47.0",
|
|
41
42
|
"bun-types": "latest",
|
|
@@ -45,5 +46,12 @@
|
|
|
45
46
|
"prettier": "^3.2.4",
|
|
46
47
|
"typescript-eslint": "^8.47.0",
|
|
47
48
|
"vitest": "^3.2.4"
|
|
49
|
+
},
|
|
50
|
+
"scripts": {
|
|
51
|
+
"build": "bun run build:tsc",
|
|
52
|
+
"build:tsc": "bun scripts/build.ts",
|
|
53
|
+
"test": "bun test",
|
|
54
|
+
"publish": "bun publish --access public",
|
|
55
|
+
"prepublishOnly": "bun run build"
|
|
48
56
|
}
|
|
49
57
|
}
|
package/src/version.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Version information
|
|
3
3
|
*/
|
|
4
|
-
export const VERSION = '0.2.
|
|
4
|
+
export const VERSION = '0.2.1';
|
|
5
5
|
export const BUILD_DATE = '2026-01-30';
|
|
6
|
-
export const RELEASE_NOTES = '
|
|
6
|
+
export const RELEASE_NOTES = 'Fix build issues and TypeScript errors';
|