chutes-plugin 0.1.0

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.
@@ -0,0 +1,513 @@
1
+ // @bun
2
+ var __create = Object.create;
3
+ var __getProtoOf = Object.getPrototypeOf;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __toESM = (mod, isNodeMode, target) => {
8
+ target = mod != null ? __create(__getProtoOf(mod)) : {};
9
+ const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
10
+ for (let key of __getOwnPropNames(mod))
11
+ if (!__hasOwnProp.call(to, key))
12
+ __defProp(to, key, {
13
+ get: () => mod[key],
14
+ enumerable: true
15
+ });
16
+ return to;
17
+ };
18
+ var __export = (target, all) => {
19
+ for (var name in all)
20
+ __defProp(target, name, {
21
+ get: all[name],
22
+ enumerable: true,
23
+ configurable: true,
24
+ set: (newValue) => all[name] = () => newValue
25
+ });
26
+ };
27
+ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
28
+ var __require = import.meta.require;
29
+
30
+ // src/cli/install.ts
31
+ var exports_install = {};
32
+ __export(exports_install, {
33
+ install: () => install
34
+ });
35
+ import * as fs from "fs";
36
+ import * as path from "path";
37
+ async function install(options) {
38
+ console.log(`\uD83D\uDC0D chutes-plugin installer
39
+ `);
40
+ console.log(`\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
41
+ `);
42
+ let installType = options.type;
43
+ if (!installType) {
44
+ console.log("Choose installation type:");
45
+ console.log("1. Project (install to .opencode/plugin/)");
46
+ console.log("2. Global (install to ~/.config/opencode/plugin/)");
47
+ console.log(`3. NPM (add to opencode.json for auto-install)
48
+ `);
49
+ const readline = await import("readline");
50
+ const rl = readline.createInterface({
51
+ input: process.stdin,
52
+ output: process.stdout
53
+ });
54
+ installType = await new Promise((resolve) => {
55
+ rl.question("> ", (answer) => {
56
+ rl.close();
57
+ resolve(answer.trim());
58
+ });
59
+ });
60
+ }
61
+ switch (installType) {
62
+ case "1":
63
+ case "project":
64
+ await installProject();
65
+ break;
66
+ case "2":
67
+ case "global":
68
+ await installGlobal();
69
+ break;
70
+ case "3":
71
+ case "npm":
72
+ await installNpm();
73
+ break;
74
+ default:
75
+ console.log("Invalid installation type. Please choose 1, 2, or 3.");
76
+ process.exit(1);
77
+ }
78
+ }
79
+ async function installProject() {
80
+ const projectDir = process.cwd();
81
+ const opencodeDir = path.join(projectDir, ".opencode");
82
+ const pluginDir = path.join(opencodeDir, "plugin", "chutes-plugin");
83
+ console.log(`Installing to project...
84
+ `);
85
+ if (!fs.existsSync(opencodeDir)) {
86
+ fs.mkdirSync(opencodeDir, { recursive: true });
87
+ }
88
+ if (!fs.existsSync(path.join(opencodeDir, "plugin"))) {
89
+ fs.mkdirSync(path.join(opencodeDir, "plugin"), { recursive: true });
90
+ }
91
+ fs.mkdirSync(pluginDir, { recursive: true });
92
+ const distDir = path.join(__dirname, "..", "..", "dist");
93
+ if (fs.existsSync(distDir)) {
94
+ fs.cpSync(distDir, path.join(pluginDir, "dist"), { recursive: true });
95
+ }
96
+ const srcCliDir = path.join(__dirname, "..");
97
+ if (fs.existsSync(srcCliDir)) {
98
+ fs.cpSync(srcCliDir, path.join(pluginDir, "src"), { recursive: true });
99
+ }
100
+ const packageJsonPath = path.join(opencodeDir, "opencode.json");
101
+ let config = {};
102
+ if (fs.existsSync(packageJsonPath)) {
103
+ const content = fs.readFileSync(packageJsonPath, "utf-8");
104
+ config = JSON.parse(content);
105
+ }
106
+ config.plugins = config.plugins || [];
107
+ if (!Array.isArray(config.plugins)) {
108
+ config.plugins = [];
109
+ }
110
+ const pluginPath = "./.opencode/plugin/chutes-plugin/dist/index.js";
111
+ if (!config.plugins.includes(pluginPath)) {
112
+ config.plugins.push(pluginPath);
113
+ }
114
+ fs.writeFileSync(packageJsonPath, JSON.stringify(config, null, 2));
115
+ console.log("\u2705 Successfully installed to project!");
116
+ console.log(`
117
+ Next steps:`);
118
+ console.log("1. Start OpenCode: opencode");
119
+ console.log("2. Connect your Chutes token: /connect chutes");
120
+ console.log(`3. Select a Chutes model from the dropdown
121
+ `);
122
+ }
123
+ async function installGlobal() {
124
+ const homeDir = process.env.HOME || process.env.USERPROFILE;
125
+ if (!homeDir) {
126
+ console.log("\u274C Error: Could not determine home directory");
127
+ process.exit(1);
128
+ }
129
+ const configDir = path.join(homeDir, ".config", "opencode");
130
+ const pluginDir = path.join(configDir, "plugin", "chutes-plugin");
131
+ console.log(`Installing globally...
132
+ `);
133
+ fs.mkdirSync(pluginDir, { recursive: true });
134
+ const distDir = path.join(__dirname, "..", "..", "dist");
135
+ if (fs.existsSync(distDir)) {
136
+ fs.cpSync(distDir, path.join(pluginDir, "dist"), { recursive: true });
137
+ }
138
+ const srcCliDir = path.join(__dirname, "..");
139
+ if (fs.existsSync(srcCliDir)) {
140
+ fs.cpSync(srcCliDir, path.join(pluginDir, "src"), { recursive: true });
141
+ }
142
+ const configPath = path.join(configDir, "opencode.json");
143
+ let config = {};
144
+ if (fs.existsSync(configPath)) {
145
+ const content = fs.readFileSync(configPath, "utf-8");
146
+ config = JSON.parse(content);
147
+ }
148
+ config.plugins = config.plugins || [];
149
+ if (!Array.isArray(config.plugins)) {
150
+ config.plugins = [];
151
+ }
152
+ const pluginPath = `${configDir}/plugin/chutes-plugin/dist/index.js`;
153
+ if (!config.plugins.includes(pluginPath)) {
154
+ config.plugins.push(pluginPath);
155
+ }
156
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
157
+ console.log("\u2705 Successfully installed globally!");
158
+ console.log(`
159
+ Next steps:`);
160
+ console.log("1. Start OpenCode: opencode");
161
+ console.log("2. Connect your Chutes token: /connect chutes");
162
+ console.log(`3. Select a Chutes model from the dropdown
163
+ `);
164
+ }
165
+ async function installNpm() {
166
+ const projectDir = process.cwd();
167
+ const configPath = path.join(projectDir, "opencode.json");
168
+ console.log(`Installing via npm...
169
+ `);
170
+ let config = {};
171
+ if (fs.existsSync(configPath)) {
172
+ const content = fs.readFileSync(configPath, "utf-8");
173
+ config = JSON.parse(content);
174
+ }
175
+ config.plugins = config.plugins || [];
176
+ if (!Array.isArray(config.plugins)) {
177
+ config.plugins = [];
178
+ }
179
+ if (!config.plugins.includes("chutes-plugin")) {
180
+ config.plugins.push("chutes-plugin");
181
+ }
182
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
183
+ console.log('\u2705 Added "chutes-plugin" to opencode.json!');
184
+ console.log(`
185
+ Next steps:`);
186
+ console.log("1. Start OpenCode: opencode");
187
+ console.log("2. The plugin will be auto-installed on first run");
188
+ console.log("3. Connect your Chutes token: /connect chutes");
189
+ console.log(`4. Select a Chutes model from the dropdown
190
+ `);
191
+ }
192
+ var __dirname = "/home/mark182/code/chutes-plugin/src/cli";
193
+ var init_install = () => {};
194
+
195
+ // src/cli/status.ts
196
+ var exports_status = {};
197
+ __export(exports_status, {
198
+ status: () => status
199
+ });
200
+ import * as fs2 from "fs";
201
+ import * as path2 from "path";
202
+ async function status() {
203
+ console.log(`\uD83D\uDC0D chutes-plugin status
204
+ `);
205
+ console.log(`\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
206
+ `);
207
+ let hasConfig = false;
208
+ let pluginPath = "";
209
+ let installType = "";
210
+ const projectDir = process.cwd();
211
+ const projectConfigPath = path2.join(projectDir, "opencode.json");
212
+ const homeDir = process.env.HOME || process.env.USERPROFILE;
213
+ const globalConfigPath = homeDir ? path2.join(homeDir, ".config", "opencode", "opencode.json") : null;
214
+ if (fs2.existsSync(projectConfigPath)) {
215
+ const content = fs2.readFileSync(projectConfigPath, "utf-8");
216
+ const config = JSON.parse(content);
217
+ const plugins = config.plugins || [];
218
+ for (const p of plugins) {
219
+ if (p.includes("chutes-plugin")) {
220
+ hasConfig = true;
221
+ installType = "npm";
222
+ pluginPath = p;
223
+ break;
224
+ }
225
+ }
226
+ const opencodeDir = path2.join(projectDir, ".opencode", "plugin", "chutes-plugin");
227
+ if (fs2.existsSync(opencodeDir)) {
228
+ hasConfig = true;
229
+ installType = "project";
230
+ pluginPath = opencodeDir;
231
+ }
232
+ }
233
+ if (!hasConfig && globalConfigPath && fs2.existsSync(globalConfigPath)) {
234
+ const content = fs2.readFileSync(globalConfigPath, "utf-8");
235
+ const config = JSON.parse(content);
236
+ const plugins = config.plugins || [];
237
+ for (const p of plugins) {
238
+ if (p.includes("chutes-plugin")) {
239
+ hasConfig = true;
240
+ installType = "global";
241
+ pluginPath = p;
242
+ break;
243
+ }
244
+ }
245
+ }
246
+ console.log(`Installation: ${hasConfig ? "\u2705 Configured" : "\u274C Not configured"}`);
247
+ if (hasConfig) {
248
+ console.log(`Type: ${installType}`);
249
+ console.log(`Path: ${pluginPath}
250
+ `);
251
+ }
252
+ const authPath = homeDir ? path2.join(homeDir, ".local", "share", "opencode", "auth.json") : null;
253
+ let hasAuth = false;
254
+ if (authPath && fs2.existsSync(authPath)) {
255
+ const content = fs2.readFileSync(authPath, "utf-8");
256
+ const auth = JSON.parse(content);
257
+ hasAuth = !!(auth.chutes || auth.CHUTES_API_TOKEN || auth.chutes_api_token);
258
+ }
259
+ console.log(`API Token: ${hasAuth ? "\u2705 Connected" : "\u26A0\uFE0F Not connected"}`);
260
+ if (!hasAuth) {
261
+ console.log(`
262
+ To connect your token:`);
263
+ console.log("1. Run: opencode");
264
+ console.log("2. Type: /connect chutes");
265
+ console.log(`3. Follow the prompts
266
+ `);
267
+ }
268
+ console.log("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501");
269
+ }
270
+ var init_status = () => {};
271
+
272
+ // src/cli/list.ts
273
+ var exports_list = {};
274
+ __export(exports_list, {
275
+ list: () => list
276
+ });
277
+ async function list() {
278
+ console.log(`\uD83D\uDC0D chutes-plugin models
279
+ `);
280
+ console.log(`\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
281
+ `);
282
+ console.log(`Fetching models from Chutes API...
283
+ `);
284
+ try {
285
+ const response = await fetch("https://llm.chutes.ai/v1/models", {
286
+ method: "GET",
287
+ headers: {
288
+ "Content-Type": "application/json"
289
+ }
290
+ });
291
+ if (!response.ok) {
292
+ console.log(`\u274C Error fetching models: ${response.status} ${response.statusText}`);
293
+ process.exit(1);
294
+ }
295
+ const data = await response.json();
296
+ const models = data.data || [];
297
+ console.log(`Found ${models.length} models:
298
+ `);
299
+ for (const model of models) {
300
+ console.log(`\u2022 ${model.id}`);
301
+ console.log(` Owner: ${model.owned_by}`);
302
+ console.log(` Pricing: $${model.pricing.prompt.toFixed(2)}/M input, $${model.pricing.completion.toFixed(2)}/M output
303
+ `);
304
+ }
305
+ console.log(`\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
306
+ `);
307
+ console.log("Tip: To use these models:");
308
+ console.log("1. Install the plugin: bunx chutes-plugin install");
309
+ console.log("2. Start OpenCode: opencode");
310
+ console.log("3. Connect token: /connect chutes");
311
+ console.log(`4. Select a Chutes model from the dropdown
312
+ `);
313
+ } catch (error) {
314
+ console.log(`\u274C Error fetching models: ${error instanceof Error ? error.message : String(error)}`);
315
+ process.exit(1);
316
+ }
317
+ }
318
+
319
+ // src/cli/refresh.ts
320
+ var exports_refresh = {};
321
+ __export(exports_refresh, {
322
+ refresh: () => refresh
323
+ });
324
+ async function refresh() {
325
+ console.log(`\uD83D\uDC0D chutes-plugin refresh
326
+ `);
327
+ console.log(`\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
328
+ `);
329
+ console.log(`Refreshing model cache...
330
+ `);
331
+ try {
332
+ const response = await fetch("https://llm.chutes.ai/v1/models", {
333
+ method: "GET",
334
+ headers: {
335
+ "Content-Type": "application/json"
336
+ }
337
+ });
338
+ if (!response.ok) {
339
+ console.log(`\u274C Error refreshing models: ${response.status} ${response.statusText}`);
340
+ process.exit(1);
341
+ }
342
+ const data = await response.json();
343
+ const models = data.data || [];
344
+ console.log(`\u2705 Successfully refreshed ${models.length} models
345
+ `);
346
+ console.log("Note: The cache will be automatically refreshed when OpenCode restarts.");
347
+ console.log(`Models are cached in-memory for 1 hour during each OpenCode session.
348
+ `);
349
+ } catch (error) {
350
+ console.log(`\u274C Error refreshing models: ${error instanceof Error ? error.message : String(error)}`);
351
+ process.exit(1);
352
+ }
353
+ }
354
+
355
+ // src/cli/doctor.ts
356
+ var exports_doctor = {};
357
+ __export(exports_doctor, {
358
+ doctor: () => doctor
359
+ });
360
+ import * as fs3 from "fs";
361
+ import * as path3 from "path";
362
+ async function doctor() {
363
+ console.log(`\uD83D\uDC0D chutes-plugin doctor
364
+ `);
365
+ console.log(`\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
366
+ `);
367
+ let checks = 0;
368
+ let passed = 0;
369
+ function check(name, result, message) {
370
+ checks++;
371
+ if (result) {
372
+ passed++;
373
+ console.log(`\u2705 ${name}`);
374
+ } else {
375
+ console.log(`\u274C ${name}`);
376
+ console.log(` ${message}`);
377
+ }
378
+ }
379
+ const projectDir = process.cwd();
380
+ const homeDir = process.env.HOME || process.env.USERPROFILE;
381
+ console.log(`Installation Checks:
382
+ `);
383
+ let hasProjectConfig = false;
384
+ let hasGlobalConfig = false;
385
+ let installType = "none";
386
+ const projectConfigPath = path3.join(projectDir, "opencode.json");
387
+ if (fs3.existsSync(projectConfigPath)) {
388
+ const content = fs3.readFileSync(projectConfigPath, "utf-8");
389
+ const config = JSON.parse(content);
390
+ const plugins = config.plugins || [];
391
+ for (const p of plugins) {
392
+ if (p.includes("chutes-plugin")) {
393
+ hasProjectConfig = true;
394
+ installType = "npm";
395
+ break;
396
+ }
397
+ }
398
+ const opencodeDir = path3.join(projectDir, ".opencode", "plugin", "chutes-plugin");
399
+ if (fs3.existsSync(opencodeDir)) {
400
+ hasProjectConfig = true;
401
+ installType = "project";
402
+ }
403
+ }
404
+ if (!hasProjectConfig && homeDir) {
405
+ const globalConfigPath = path3.join(homeDir, ".config", "opencode", "opencode.json");
406
+ if (fs3.existsSync(globalConfigPath)) {
407
+ const content = fs3.readFileSync(globalConfigPath, "utf-8");
408
+ const config = JSON.parse(content);
409
+ const plugins = config.plugins || [];
410
+ for (const p of plugins) {
411
+ if (p.includes("chutes-plugin")) {
412
+ hasGlobalConfig = true;
413
+ installType = "global";
414
+ break;
415
+ }
416
+ }
417
+ }
418
+ }
419
+ check("Plugin installed", hasProjectConfig || hasGlobalConfig, installType === "none" ? "Run: bunx chutes-plugin install" : `Installed as ${installType}`);
420
+ console.log(`
421
+ API Checks:
422
+ `);
423
+ let hasAuth = false;
424
+ if (homeDir) {
425
+ const authPath = path3.join(homeDir, ".local", "share", "opencode", "auth.json");
426
+ if (fs3.existsSync(authPath)) {
427
+ const content = fs3.readFileSync(authPath, "utf-8");
428
+ const auth = JSON.parse(content);
429
+ hasAuth = !!(auth.chutes || auth.CHUTES_API_TOKEN || auth.chutes_api_token);
430
+ }
431
+ }
432
+ check("API token connected", hasAuth, "Run: opencode, then type: /connect chutes");
433
+ console.log(`
434
+ Network Checks:
435
+ `);
436
+ try {
437
+ const response = await fetch("https://llm.chutes.ai/v1/models", {
438
+ method: "GET",
439
+ headers: { "Content-Type": "application/json" }
440
+ });
441
+ check("Can reach Chutes API", response.ok, `HTTP ${response.status}: ${response.statusText}`);
442
+ if (response.ok) {
443
+ const data = await response.json();
444
+ console.log(` Found ${data.data?.length || 0} models available
445
+ `);
446
+ }
447
+ } catch (error) {
448
+ check("Can reach Chutes API", false, `Connection failed: ${error instanceof Error ? error.message : String(error)}`);
449
+ }
450
+ console.log(`\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
451
+ `);
452
+ console.log(`Results: ${passed}/${checks} checks passed
453
+ `);
454
+ if (passed === checks) {
455
+ console.log(`\uD83C\uDF89 Everything looks good! You're ready to use chutes-plugin.
456
+ `);
457
+ } else {
458
+ console.log(`\u26A0\uFE0F Some checks failed. Please address the issues above.
459
+ `);
460
+ }
461
+ }
462
+ var init_doctor = () => {};
463
+
464
+ // src/cli/index.ts
465
+ import cac from "cac";
466
+ var cli = cac("chutes-plugin");
467
+ cli.version("0.1.0");
468
+ cli.usage(`
469
+ \uD83D\uDC0D chutes-plugin
470
+
471
+ A plugin for OpenCode that provides access to 48+ state-of-the-art AI models through the Chutes API.
472
+
473
+ Usage:
474
+ $ chutes-plugin <command>
475
+
476
+ Commands:
477
+ install Install the plugin (project, global, or npm)
478
+ status Check plugin status and configuration
479
+ list List available models from the Chutes API
480
+ refresh Force refresh the model cache
481
+ doctor Verify that everything is configured correctly
482
+
483
+ Examples:
484
+ $ chutes-plugin install
485
+ $ chutes-plugin status
486
+ $ chutes-plugin list
487
+ $ chutes-plugin refresh
488
+ $ chutes-plugin doctor
489
+ `);
490
+ cli.command("install", "Install the plugin to OpenCode").option("--type <type>", "Installation type: project, global, or npm").action(async (options) => {
491
+ const { install: install2 } = await Promise.resolve().then(() => (init_install(), exports_install));
492
+ await install2(options);
493
+ });
494
+ cli.command("status", "Check plugin status and configuration").action(async () => {
495
+ const { status: status2 } = await Promise.resolve().then(() => (init_status(), exports_status));
496
+ await status2();
497
+ });
498
+ cli.command("list", "List available models from the Chutes API").action(async () => {
499
+ const { list: list2 } = await Promise.resolve().then(() => exports_list);
500
+ await list2();
501
+ });
502
+ cli.command("refresh", "Force refresh the model cache").action(async () => {
503
+ const { refresh: refresh2 } = await Promise.resolve().then(() => exports_refresh);
504
+ await refresh2();
505
+ });
506
+ cli.command("doctor", "Verify that everything is configured correctly").action(async () => {
507
+ const { doctor: doctor2 } = await Promise.resolve().then(() => (init_doctor(), exports_doctor));
508
+ await doctor2();
509
+ });
510
+ cli.parse();
511
+ if (process.argv.length === 2) {
512
+ cli.outputHelp();
513
+ }
@@ -0,0 +1,15 @@
1
+ declare module 'chutes-plugin' {
2
+ import type { Plugin } from '@opencode-ai/plugin';
3
+
4
+ interface ChutesPluginConfig {
5
+ apiToken?: string;
6
+ autoRefresh?: boolean;
7
+ refreshInterval?: number;
8
+ defaultModel?: string;
9
+ modelFilter?: string[];
10
+ }
11
+
12
+ export const ChutesPlugin: Plugin;
13
+
14
+ export default ChutesPlugin;
15
+ }