@genflowai/opencode-autosetup 1.0.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.
Files changed (3) hide show
  1. package/README.md +265 -0
  2. package/package.json +20 -0
  3. package/setup-opencode.js +199 -0
package/README.md ADDED
@@ -0,0 +1,265 @@
1
+ # GenFlow OpenCode Auto Setup
2
+
3
+ Auto setup provider GenFlowAI untuk OpenCode lewat npm.
4
+
5
+ Script ini akan cek OpenCode, install otomatis jika belum ada, meminta API key GenFlow, meminta model yang ingin dipakai, lalu otomatis membuat atau memperbarui config OpenCode di komputer user.
6
+
7
+ ## Syarat
8
+
9
+ - Node.js minimal versi 18
10
+ - npm
11
+ - API key GenFlowAI
12
+
13
+ API docs: <https://genflowai.co/api-docs>
14
+
15
+ Daftar model: <https://genflowai.co/models>
16
+
17
+ ## Cara pakai cepat
18
+
19
+ Jalankan:
20
+
21
+ ```bash
22
+ npx @genflowai/opencode-autosetup
23
+ ```
24
+
25
+ Lalu isi prompt:
26
+
27
+ ```text
28
+ Masukkan GenFlow API key: gf_xxxxxxxxx
29
+ Model [gpt-5.5]: gpt-5.5
30
+ ```
31
+
32
+ Jika ingin pakai default model `gpt-5.5`, cukup tekan Enter saat ditanya model.
33
+
34
+ ## Cara pakai dari source lokal
35
+
36
+ Jika repo/script ini sudah ada di komputer:
37
+
38
+ ```bash
39
+ npm run setup
40
+ ```
41
+
42
+ ## Apa yang dilakukan script?
43
+
44
+ 1. Mengecek apakah command `opencode` sudah tersedia.
45
+ 2. Jika belum tersedia, script install otomatis dengan:
46
+
47
+ ```bash
48
+ npm install -g opencode-ai@latest
49
+ ```
50
+
51
+ 3. Meminta API key GenFlowAI.
52
+ 4. Mengambil daftar model dari:
53
+
54
+ ```text
55
+ https://genflowai.co/v1/models
56
+ ```
57
+
58
+ 5. Menampilkan beberapa contoh model tersedia.
59
+ 6. Meminta user memasukkan model manual.
60
+ 7. Validasi model jika endpoint model bisa diakses.
61
+ 8. Menulis config OpenCode ke home directory user.
62
+
63
+ Lokasi config default:
64
+
65
+ ```text
66
+ ~/.config/opencode/opencode.json
67
+ ```
68
+
69
+ Contoh di Windows akan menjadi:
70
+
71
+ ```text
72
+ C:\Users\NAMA_USER\.config\opencode\opencode.json
73
+ ```
74
+
75
+ Tidak ada path user hardcoded. Path otomatis mengikuti komputer masing-masing user.
76
+
77
+ ## Contoh config yang dibuat
78
+
79
+ Jika user memilih model `gpt-5.5`, script akan membuat config seperti ini:
80
+
81
+ ```json
82
+ {
83
+ "$schema": "https://opencode.ai/config.json",
84
+ "model": "genflowai/gpt-5.5",
85
+ "provider": {
86
+ "genflowai": {
87
+ "npm": "@ai-sdk/openai-compatible",
88
+ "name": "GenFlowAI",
89
+ "options": {
90
+ "baseURL": "https://genflowai.co/v1",
91
+ "apiKey": "API_KEY_USER"
92
+ },
93
+ "models": {
94
+ "gpt-5.5": {
95
+ "name": "gpt-5.5"
96
+ }
97
+ }
98
+ }
99
+ }
100
+ }
101
+ ```
102
+
103
+ ## Memilih model
104
+
105
+ User bisa memasukkan model apa pun yang tersedia di:
106
+
107
+ ```text
108
+ https://genflowai.co/models
109
+ ```
110
+
111
+ Contoh model:
112
+
113
+ ```text
114
+ gpt-5.5
115
+ gpt-5.5-high
116
+ gpt-5.5-medium
117
+ gpt-5.5-low
118
+ gpt-5.4
119
+ gpt-5.3
120
+ gpt-5.2
121
+ gpt-5.1
122
+ claude-opus-4.7
123
+ claude-sonnet-4.6
124
+ gemini-3-pro-preview
125
+ deepseek-v3.2
126
+ ```
127
+
128
+ Saat prompt muncul:
129
+
130
+ ```text
131
+ Model [gpt-5.5]:
132
+ ```
133
+
134
+ Pilihan:
135
+
136
+ - tekan Enter → pakai `gpt-5.5`
137
+ - ketik manual → contoh `gpt-5.5-high`
138
+
139
+ ## Mode non-interaktif
140
+
141
+ Cocok untuk automation/CI/script.
142
+
143
+ Linux/macOS:
144
+
145
+ ```bash
146
+ GENFLOW_API_KEY="gf_xxxxxxxxx" npx @genflowai/opencode-autosetup --model gpt-5.5
147
+ ```
148
+
149
+ Windows PowerShell:
150
+
151
+ ```powershell
152
+ $env:GENFLOW_API_KEY="gf_xxxxxxxxx"; npx @genflowai/opencode-autosetup --model gpt-5.5
153
+ ```
154
+
155
+ Atau langsung lewat argumen:
156
+
157
+ ```bash
158
+ npx @genflowai/opencode-autosetup --api-key gf_xxxxxxxxx --model gpt-5.5
159
+ ```
160
+
161
+ Jika ingin melewati cek/install OpenCode:
162
+
163
+ ```bash
164
+ npx @genflowai/opencode-autosetup --skip-opencode-install --api-key gf_xxxxxxxxx --model gpt-5.5
165
+ ```
166
+
167
+ ## Custom lokasi config
168
+
169
+ Defaultnya script menulis ke:
170
+
171
+ ```text
172
+ ~/.config/opencode/opencode.json
173
+ ```
174
+
175
+ Untuk test atau custom lokasi, pakai `OPENCODE_CONFIG_DIR`.
176
+
177
+ Linux/macOS:
178
+
179
+ ```bash
180
+ OPENCODE_CONFIG_DIR="/tmp/opencode" GENFLOW_API_KEY="gf_xxxxxxxxx" npx @genflowai/opencode-autosetup --model gpt-5.5
181
+ ```
182
+
183
+ Windows PowerShell:
184
+
185
+ ```powershell
186
+ $env:OPENCODE_CONFIG_DIR="C:\Temp\opencode"; $env:GENFLOW_API_KEY="gf_xxxxxxxxx"; npx @genflowai/opencode-autosetup --model gpt-5.5
187
+ ```
188
+
189
+ ## Setelah setup
190
+
191
+ Jalankan OpenCode:
192
+
193
+ ```bash
194
+ opencode
195
+ ```
196
+
197
+ OpenCode akan memakai provider:
198
+
199
+ ```text
200
+ genflowai
201
+ ```
202
+
203
+ Dengan model:
204
+
205
+ ```text
206
+ genflowai/NAMA_MODEL
207
+ ```
208
+
209
+ Contoh:
210
+
211
+ ```text
212
+ genflowai/gpt-5.5
213
+ ```
214
+
215
+ ## Troubleshooting
216
+
217
+ ### `API key wajib diisi.`
218
+
219
+ API key kosong. Jalankan ulang lalu isi API key GenFlowAI.
220
+
221
+ ### `Model tidak ditemukan`
222
+
223
+ Model yang diketik tidak ada di endpoint model GenFlowAI.
224
+
225
+ Cek daftar model:
226
+
227
+ ```text
228
+ https://genflowai.co/models
229
+ ```
230
+
231
+ Lalu jalankan ulang dengan model yang valid.
232
+
233
+ ### `npm` tidak bisa jalan di PowerShell
234
+
235
+ Jika PowerShell memblokir `npm.ps1`, pakai:
236
+
237
+ ```powershell
238
+ cmd /c "npm run setup"
239
+ ```
240
+
241
+ atau:
242
+
243
+ ```powershell
244
+ cmd /c "npx @genflowai/opencode-autosetup"
245
+ ```
246
+
247
+ ### Install OpenCode gagal
248
+
249
+ Script otomatis menjalankan:
250
+
251
+ ```bash
252
+ npm install -g opencode-ai@latest
253
+ ```
254
+
255
+ Jika gagal, cek koneksi internet dan permission npm global. Setelah berhasil, restart terminal lalu jalankan ulang script.
256
+
257
+ Jika OpenCode sudah terinstall tapi script tetap ingin install, jalankan dengan:
258
+
259
+ ```bash
260
+ npx @genflowai/opencode-autosetup --skip-opencode-install
261
+ ```
262
+
263
+ ### Config lama sudah ada
264
+
265
+ Script akan membaca config lama lalu menambahkan/memperbarui provider `genflowai`. Config provider lain tetap dipertahankan.
package/package.json ADDED
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "@genflowai/opencode-autosetup",
3
+ "version": "1.0.0",
4
+ "description": "Auto setup GenFlowAI provider for OpenCode",
5
+ "type": "module",
6
+ "bin": {
7
+ "genflow-opencode-autosetup": "setup-opencode.js",
8
+ "genflowai-opencode-autosetup": "setup-opencode.js"
9
+ },
10
+ "files": [
11
+ "setup-opencode.js",
12
+ "README.md"
13
+ ],
14
+ "scripts": {
15
+ "setup": "node setup-opencode.js"
16
+ },
17
+ "engines": {
18
+ "node": ">=18"
19
+ }
20
+ }
@@ -0,0 +1,199 @@
1
+ #!/usr/bin/env node
2
+ import { createInterface } from "node:readline/promises";
3
+ import { stdin as input, stdout as output } from "node:process";
4
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
5
+ import { existsSync } from "node:fs";
6
+ import { join } from "node:path";
7
+ import { homedir } from "node:os";
8
+ import { spawn } from "node:child_process";
9
+
10
+ const PROVIDER_ID = "genflowai";
11
+ const BASE_URL = "https://genflowai.co/v1";
12
+ const MODELS_URL = `${BASE_URL}/models`;
13
+ const DEFAULT_MODEL = "gpt-5.5";
14
+ const CONFIG_DIR = process.env.OPENCODE_CONFIG_DIR || join(homedir(), ".config", "opencode");
15
+ const CONFIG_PATH = join(CONFIG_DIR, "opencode.json");
16
+
17
+ function getArgValue(name) {
18
+ const index = process.argv.indexOf(name);
19
+ return index === -1 ? "" : process.argv[index + 1] ?? "";
20
+ }
21
+
22
+ function hasArg(name) {
23
+ return process.argv.includes(name);
24
+ }
25
+
26
+ function run(command, args) {
27
+ return new Promise((resolve, reject) => {
28
+ const child = spawnProcess(command, args, "inherit");
29
+ child.on("error", reject);
30
+ child.on("close", (code) => {
31
+ if (code === 0) {
32
+ resolve();
33
+ return;
34
+ }
35
+
36
+ reject(new Error(`${command} ${args.join(" ")} keluar dengan kode ${code}`));
37
+ });
38
+ });
39
+ }
40
+
41
+ function runQuiet(command, args) {
42
+ return new Promise((resolve) => {
43
+ const child = spawnProcess(command, args, "ignore");
44
+ child.on("error", () => resolve(false));
45
+ child.on("close", (code) => resolve(code === 0));
46
+ });
47
+ }
48
+
49
+ function spawnProcess(command, args, stdio) {
50
+ if (process.platform !== "win32") {
51
+ return spawn(command, args, { shell: false, stdio });
52
+ }
53
+
54
+ return spawn(process.env.ComSpec || "cmd.exe", ["/d", "/s", "/c", command, ...args], { shell: false, stdio });
55
+ }
56
+
57
+ function npmCommand() {
58
+ return process.platform === "win32" ? "npm.cmd" : "npm";
59
+ }
60
+
61
+ function opencodeCommand() {
62
+ return process.platform === "win32" ? "opencode.cmd" : "opencode";
63
+ }
64
+
65
+ async function ensureOpenCodeInstalled() {
66
+ if (hasArg("--skip-opencode-install")) {
67
+ console.log("Skip cek/install OpenCode.");
68
+ return;
69
+ }
70
+
71
+ const installed = await runQuiet(opencodeCommand(), ["--version"]);
72
+
73
+ if (installed) {
74
+ console.log("OpenCode sudah terinstall.");
75
+ return;
76
+ }
77
+
78
+ console.log("OpenCode belum terinstall. Menginstall via npm...");
79
+ await run(npmCommand(), ["install", "-g", "opencode-ai@latest"]);
80
+
81
+ const installedAfterInstall = await runQuiet(opencodeCommand(), ["--version"]);
82
+ if (!installedAfterInstall) {
83
+ throw new Error("OpenCode sudah diinstall, tapi command `opencode` belum tersedia di PATH. Restart terminal lalu coba lagi.");
84
+ }
85
+
86
+ console.log("OpenCode berhasil terinstall.");
87
+ }
88
+
89
+ function stripJsonComments(value) {
90
+ return value
91
+ .replace(/\/\*[\s\S]*?\*\//g, "")
92
+ .replace(/(^|[^:])\/\/.*$/gm, "$1");
93
+ }
94
+
95
+ async function readExistingConfig() {
96
+ if (!existsSync(CONFIG_PATH)) {
97
+ return {};
98
+ }
99
+
100
+ const raw = await readFile(CONFIG_PATH, "utf8");
101
+ return JSON.parse(stripJsonComments(raw));
102
+ }
103
+
104
+ async function fetchAvailableModels() {
105
+ try {
106
+ const response = await fetch(MODELS_URL);
107
+
108
+ if (!response.ok) {
109
+ return [];
110
+ }
111
+
112
+ const payload = await response.json();
113
+ return Array.isArray(payload.data)
114
+ ? payload.data.map((model) => model.id).filter((model) => typeof model === "string")
115
+ : [];
116
+ } catch {
117
+ return [];
118
+ }
119
+ }
120
+
121
+ function printModelHint(models) {
122
+ if (models.length === 0) {
123
+ console.log(`Daftar model: ${MODELS_URL}`);
124
+ return;
125
+ }
126
+
127
+ console.log("Model tersedia contoh:");
128
+ for (const model of models.slice(0, 12)) {
129
+ console.log(`- ${model}`);
130
+ }
131
+ console.log(`Total model: ${models.length}. Lihat lengkap: https://genflowai.co/models`);
132
+ }
133
+
134
+ function buildConfig(existingConfig, apiKey, model) {
135
+ return {
136
+ ...existingConfig,
137
+ $schema: existingConfig.$schema ?? "https://opencode.ai/config.json",
138
+ model: `${PROVIDER_ID}/${model}`,
139
+ provider: {
140
+ ...(existingConfig.provider ?? {}),
141
+ [PROVIDER_ID]: {
142
+ npm: "@ai-sdk/openai-compatible",
143
+ name: "GenFlowAI",
144
+ options: {
145
+ baseURL: BASE_URL,
146
+ apiKey
147
+ },
148
+ models: {
149
+ ...(existingConfig.provider?.[PROVIDER_ID]?.models ?? {}),
150
+ [model]: {
151
+ name: model
152
+ }
153
+ }
154
+ }
155
+ }
156
+ };
157
+ }
158
+
159
+ async function main() {
160
+ const rl = createInterface({ input, output });
161
+
162
+ try {
163
+ await ensureOpenCodeInstalled();
164
+
165
+ const apiKey = (getArgValue("--api-key") || process.env.GENFLOW_API_KEY || await rl.question("Masukkan GenFlow API key: ")).trim();
166
+
167
+ if (!apiKey) {
168
+ throw new Error("API key wajib diisi.");
169
+ }
170
+
171
+ const availableModels = await fetchAvailableModels();
172
+ printModelHint(availableModels);
173
+
174
+ const modelInput = (getArgValue("--model") || await rl.question(`Model [${DEFAULT_MODEL}]: `)).trim();
175
+ const model = modelInput || DEFAULT_MODEL;
176
+
177
+ if (availableModels.length > 0 && !availableModels.includes(model)) {
178
+ throw new Error(`Model "${model}" tidak ditemukan di ${MODELS_URL}. Cek https://genflowai.co/models`);
179
+ }
180
+
181
+ const existingConfig = await readExistingConfig();
182
+ const nextConfig = buildConfig(existingConfig, apiKey, model);
183
+
184
+ await mkdir(CONFIG_DIR, { recursive: true });
185
+ await writeFile(CONFIG_PATH, `${JSON.stringify(nextConfig, null, 2)}\n`, "utf8");
186
+
187
+ console.log(`\nSelesai. Config opencode ditulis ke: ${CONFIG_PATH}`);
188
+ console.log(`Provider: ${PROVIDER_ID}`);
189
+ console.log(`Model: ${PROVIDER_ID}/${model}`);
190
+ console.log("Jalankan: opencode");
191
+ } finally {
192
+ rl.close();
193
+ }
194
+ }
195
+
196
+ main().catch((error) => {
197
+ console.error(`Gagal setup opencode: ${error.message}`);
198
+ process.exitCode = 1;
199
+ });