@gilangranggaid/kilua-agent 1.0.7 → 1.0.8
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/bin/kilua.js +31 -42
- package/bin/kilua.mjs +31 -42
- package/package.json +1 -1
package/bin/kilua.js
CHANGED
|
@@ -92,7 +92,7 @@ const TOOLS_OPENAI = [
|
|
|
92
92
|
type: "function",
|
|
93
93
|
function: {
|
|
94
94
|
name: "run_cmd",
|
|
95
|
-
description: "Menjalankan perintah terminal lokal untuk instalasi dependencies, test, build, atau verifikasi project.",
|
|
95
|
+
description: "Menjalankan perintah terminal lokal untuk instalasi dependencies, test, build, install skill (npx skills add), atau verifikasi project.",
|
|
96
96
|
parameters: { type: "object", properties: { command: { type: "string" } }, required: ["command"] }
|
|
97
97
|
}
|
|
98
98
|
}
|
|
@@ -148,7 +148,7 @@ async function runInteractiveConfig() {
|
|
|
148
148
|
|
|
149
149
|
console.log("\x1b[35m=== KILUA CONFIG ===\x1b[0m\nPath: " + SETTINGS_PATH);
|
|
150
150
|
console.log("1) 9Router Local / Claude Code Proxy (Port 20128)");
|
|
151
|
-
console.log("2) TokenHarbor /
|
|
151
|
+
console.log("2) TokenHarbor / OpenRouter / Custom (OpenAI-compatible)");
|
|
152
152
|
console.log("3) Google Gemini (AI Studio Key)\n");
|
|
153
153
|
|
|
154
154
|
const choice = (await promptQuestion(rl, "Pilihan [1/2/3] (default 1): ")).trim() || "1";
|
|
@@ -156,21 +156,19 @@ async function runInteractiveConfig() {
|
|
|
156
156
|
|
|
157
157
|
if (choice === "1") {
|
|
158
158
|
const defaultUrl = "http://127.0.0.1:20128/v1";
|
|
159
|
-
const defaultModel = "harobor";
|
|
160
|
-
|
|
161
159
|
const baseUrl = (await promptQuestion(rl, `Base URL (${defaultUrl}): `)).trim() || defaultUrl;
|
|
162
|
-
const key = (await promptQuestion(rl, `API Key/Token (kosongkan jika
|
|
163
|
-
const model = (await promptQuestion(rl, `Model (
|
|
160
|
+
const key = (await promptQuestion(rl, `API Key/Token (kosongkan jika lokal): `)).trim();
|
|
161
|
+
const model = (await promptQuestion(rl, `Nama Model yang ingin dipakai di 9Router (contoh: harobor): `)).trim();
|
|
164
162
|
|
|
165
163
|
settings = {
|
|
166
164
|
provider: "anthropic",
|
|
167
165
|
base_url: baseUrl.replace(/\/+$/, ""),
|
|
168
166
|
api_key: key,
|
|
169
|
-
model
|
|
167
|
+
model: model || "harobor"
|
|
170
168
|
};
|
|
171
169
|
} else if (choice === "3") {
|
|
172
170
|
const key = (await promptQuestion(rl, "Masukkan GEMINI_API_KEY: ")).trim();
|
|
173
|
-
const model = (await promptQuestion(rl, "Nama Model (gemini-3.5-flash-lite): ")).trim() || "gemini-3.5-flash-lite";
|
|
171
|
+
const model = (await promptQuestion(rl, "Nama Model (contoh: gemini-3.5-flash-lite): ")).trim() || "gemini-3.5-flash-lite";
|
|
174
172
|
settings = {
|
|
175
173
|
provider: "openai",
|
|
176
174
|
base_url: "https://generativelanguage.googleapis.com/v1beta/openai",
|
|
@@ -179,9 +177,9 @@ async function runInteractiveConfig() {
|
|
|
179
177
|
};
|
|
180
178
|
} else {
|
|
181
179
|
console.log("Contoh Base URL: https://tokenharbor.ai/v1");
|
|
182
|
-
const baseUrl = (await promptQuestion(rl, "Base URL
|
|
180
|
+
const baseUrl = (await promptQuestion(rl, "Base URL: ")).trim() || "https://tokenharbor.ai/v1";
|
|
183
181
|
const key = (await promptQuestion(rl, "API Key: ")).trim();
|
|
184
|
-
const model = (await promptQuestion(rl, "Model (deepseek-v4.1-flash:free): ")).trim() || "deepseek-v4.1-flash:free";
|
|
182
|
+
const model = (await promptQuestion(rl, "Nama Model (contoh: deepseek-v4.1-flash:free): ")).trim() || "deepseek-v4.1-flash:free";
|
|
185
183
|
settings = {
|
|
186
184
|
provider: "openai",
|
|
187
185
|
api_key: key,
|
|
@@ -236,13 +234,15 @@ function buildSystemPrompt() {
|
|
|
236
234
|
return `Kamu KILUA, AI Coding Agent otonom di terminal lokal. Folder aktif: ${process.cwd()}.
|
|
237
235
|
KEMAMPUAN TOOLS:
|
|
238
236
|
- read_file, write_file, edit_file, list_dir
|
|
239
|
-
- run_cmd: menjalankan perintah terminal lokal (npm, npx, git, node, python, build, test, curl, dsb).
|
|
237
|
+
- run_cmd: menjalankan perintah terminal lokal (npm, npx, git, node, python, build, test, curl, install skill, dsb).
|
|
240
238
|
|
|
241
|
-
ATURAN OTONOM KILUA (SELF-TESTING):
|
|
239
|
+
ATURAN OTONOM KILUA (SELF-TESTING & AUTO-INSTALL SKILL):
|
|
242
240
|
1. Jika pengguna meminta membuat project/fitur/skrip, JANGAN langsung serahkan begitu saja. Kamu HARUS mencoba atau memvalidasinya sendiri terlebih dahulu menggunakan run_cmd (misal: jalankan skrip, test, build, atau cek sintaks).
|
|
243
241
|
2. Jika ada error saat kamu mencoba, perbaiki langsung menggunakan edit_file/write_file sampai berhasil.
|
|
244
242
|
3. Setelah berhasil dicoba dan dipastikan tidak error, barulah beri tahu pengguna hasil dan cara menjalankannya.
|
|
245
|
-
4.
|
|
243
|
+
4. Jika pengguna di chat menyuruh kamu install skill (misal: "install skill vercel-labs/skills@find-skills" atau skill lain), jalankan run_cmd dengan perintah:
|
|
244
|
+
npx skills add <nama-skill> --cwd "${SKILLS_DIR}"
|
|
245
|
+
Lalu beri tahu pengguna bahwa skill tersebut telah siap dipakai.${skillsInfo}
|
|
246
246
|
|
|
247
247
|
Respon ringkas, padat, dan bertindak langsung.`;
|
|
248
248
|
}
|
|
@@ -454,11 +454,12 @@ function printHelp() {
|
|
|
454
454
|
\x1b[1m\x1b[35m=== PERINTAH SLASH KILUA (/) ===\x1b[0m
|
|
455
455
|
\x1b[36m/help\x1b[0m Lihat panduan perintah ini
|
|
456
456
|
\x1b[36m/models\x1b[0m Lihat dan ganti model AI saat ini
|
|
457
|
-
\x1b[36m/skills\x1b[0m Lihat daftar skills yang terpasang
|
|
458
|
-
\x1b[36m/install-skill\x1b[0m Pasang skill baru (misal: /install-skill vercel-labs/skills@find-skills)
|
|
457
|
+
\x1b[36m/skills\x1b[0m Lihat daftar skills yang terpasang di Kilua
|
|
459
458
|
\x1b[36m/clear\x1b[0m Bersihkan riwayat percakapan sesi ini
|
|
460
459
|
\x1b[36m/config\x1b[0m Ubah API Key, Provider, atau Base URL
|
|
461
460
|
\x1b[36m/exit\x1b[0m Keluar dari Kilua Agent
|
|
461
|
+
|
|
462
|
+
\x1b[90mTips: Untuk menginstall skill baru, cukup suruh Kilua di chat (misal: "tolong install skill find-skills")!\x1b[0m
|
|
462
463
|
`);
|
|
463
464
|
}
|
|
464
465
|
|
|
@@ -472,12 +473,12 @@ async function handleSlashCommand(cmd, settings, convo, rl) {
|
|
|
472
473
|
}
|
|
473
474
|
|
|
474
475
|
if (action === "/models" || action === "/model") {
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
console.log(
|
|
480
|
-
const newModel = (await promptQuestion(rl, `Ganti model (Enter untuk tetap '${settings.model}'): `)).trim();
|
|
476
|
+
if (!settings.base_url || !settings.api_key) {
|
|
477
|
+
console.log(`\n\x1b[33m[!] Belum terhubung ke config provider. Jalankan /config terlebih dahulu.\x1b[0m\n`);
|
|
478
|
+
return settings;
|
|
479
|
+
}
|
|
480
|
+
console.log(`\n\x1b[33mModel aktif saat ini:\x1b[0m \x1b[32m${settings.model}\x1b[0m (Provider: ${settings.base_url})`);
|
|
481
|
+
const newModel = (await promptQuestion(rl, `Ganti nama model (Enter untuk tetap '${settings.model}'): `)).trim();
|
|
481
482
|
if (newModel) {
|
|
482
483
|
settings.model = newModel;
|
|
483
484
|
saveSettings(settings);
|
|
@@ -490,8 +491,8 @@ async function handleSlashCommand(cmd, settings, convo, rl) {
|
|
|
490
491
|
const list = listInstalledSkills();
|
|
491
492
|
console.log(`\n\x1b[35m=== SKILLS TERPASANG (${SKILLS_DIR}) ===\x1b[0m`);
|
|
492
493
|
if (!list.length) {
|
|
493
|
-
console.log(`
|
|
494
|
-
console.log(`
|
|
494
|
+
console.log(`Belum ada skill tambahan terpasang.`);
|
|
495
|
+
console.log(`Suruh Kilua di chat untuk install, misal: \x1b[36m"Kilua, tolong install skill vercel-labs/skills@find-skills"\x1b[0m`);
|
|
495
496
|
} else {
|
|
496
497
|
for (const s of list) {
|
|
497
498
|
console.log(`- \x1b[32m${s.name}\x1b[0m: ${s.desc}`);
|
|
@@ -501,22 +502,6 @@ async function handleSlashCommand(cmd, settings, convo, rl) {
|
|
|
501
502
|
return settings;
|
|
502
503
|
}
|
|
503
504
|
|
|
504
|
-
if (action === "/install-skill") {
|
|
505
|
-
const target = parts.slice(1).join(" ").trim();
|
|
506
|
-
if (!target) {
|
|
507
|
-
console.log(`\x1b[33mContoh penggunaan: /install-skill vercel-labs/skills@find-skills\x1b[0m`);
|
|
508
|
-
return settings;
|
|
509
|
-
}
|
|
510
|
-
console.log(`\x1b[35m[Memasang skill ${target}...]\x1b[0m`);
|
|
511
|
-
try {
|
|
512
|
-
execSync(`npx skills add ${target}`, { cwd: SKILLS_DIR, stdio: "inherit" });
|
|
513
|
-
console.log(`\x1b[32m✓ Skill ${target} berhasil dipasang!\x1b[0m\n`);
|
|
514
|
-
} catch (e) {
|
|
515
|
-
console.error(`[!] Gagal memasang skill:`, e.message);
|
|
516
|
-
}
|
|
517
|
-
return settings;
|
|
518
|
-
}
|
|
519
|
-
|
|
520
505
|
if (action === "/clear") {
|
|
521
506
|
convo.length = 0;
|
|
522
507
|
console.clear();
|
|
@@ -545,8 +530,12 @@ async function main() {
|
|
|
545
530
|
|
|
546
531
|
let settings = loadSettings();
|
|
547
532
|
|
|
548
|
-
|
|
549
|
-
|
|
533
|
+
// Validasi ketat: jika belum ada base_url atau api_key, WAJIB setup dulu
|
|
534
|
+
const isLocalProxy = settings.base_url?.includes("127.0.0.1") || settings.base_url?.includes("localhost");
|
|
535
|
+
const hasValidConfig = settings.base_url && (settings.api_key || isLocalProxy);
|
|
536
|
+
|
|
537
|
+
if (!hasValidConfig) {
|
|
538
|
+
console.log("\x1b[33m[!] Belum ada konfigurasi AI key / provider.\x1b[0m");
|
|
550
539
|
settings = await runInteractiveConfig();
|
|
551
540
|
}
|
|
552
541
|
|
|
@@ -559,7 +548,7 @@ async function main() {
|
|
|
559
548
|
console.log("\x1b[1m\x1b[35m=== KILUA AI CLI AGENT ===\x1b[0m");
|
|
560
549
|
console.log(`CWD : \x1b[33m${process.cwd()}\x1b[0m`);
|
|
561
550
|
console.log(`Provider: \x1b[32m${settings.base_url}\x1b[0m (${settings.model})`);
|
|
562
|
-
console.log(`Config : \x1b[90m${SETTINGS_PATH}\x1b[0m (ketik \x1b[36m/help\x1b[0m untuk
|
|
551
|
+
console.log(`Config : \x1b[90m${SETTINGS_PATH}\x1b[0m (ketik \x1b[36m/help\x1b[0m untuk panduan)\n`);
|
|
563
552
|
|
|
564
553
|
let rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
565
554
|
const ask = () => {
|
package/bin/kilua.mjs
CHANGED
|
@@ -92,7 +92,7 @@ const TOOLS_OPENAI = [
|
|
|
92
92
|
type: "function",
|
|
93
93
|
function: {
|
|
94
94
|
name: "run_cmd",
|
|
95
|
-
description: "Menjalankan perintah terminal lokal untuk instalasi dependencies, test, build, atau verifikasi project.",
|
|
95
|
+
description: "Menjalankan perintah terminal lokal untuk instalasi dependencies, test, build, install skill (npx skills add), atau verifikasi project.",
|
|
96
96
|
parameters: { type: "object", properties: { command: { type: "string" } }, required: ["command"] }
|
|
97
97
|
}
|
|
98
98
|
}
|
|
@@ -148,7 +148,7 @@ async function runInteractiveConfig() {
|
|
|
148
148
|
|
|
149
149
|
console.log("\x1b[35m=== KILUA CONFIG ===\x1b[0m\nPath: " + SETTINGS_PATH);
|
|
150
150
|
console.log("1) 9Router Local / Claude Code Proxy (Port 20128)");
|
|
151
|
-
console.log("2) TokenHarbor /
|
|
151
|
+
console.log("2) TokenHarbor / OpenRouter / Custom (OpenAI-compatible)");
|
|
152
152
|
console.log("3) Google Gemini (AI Studio Key)\n");
|
|
153
153
|
|
|
154
154
|
const choice = (await promptQuestion(rl, "Pilihan [1/2/3] (default 1): ")).trim() || "1";
|
|
@@ -156,21 +156,19 @@ async function runInteractiveConfig() {
|
|
|
156
156
|
|
|
157
157
|
if (choice === "1") {
|
|
158
158
|
const defaultUrl = "http://127.0.0.1:20128/v1";
|
|
159
|
-
const defaultModel = "harobor";
|
|
160
|
-
|
|
161
159
|
const baseUrl = (await promptQuestion(rl, `Base URL (${defaultUrl}): `)).trim() || defaultUrl;
|
|
162
|
-
const key = (await promptQuestion(rl, `API Key/Token (kosongkan jika
|
|
163
|
-
const model = (await promptQuestion(rl, `Model (
|
|
160
|
+
const key = (await promptQuestion(rl, `API Key/Token (kosongkan jika lokal): `)).trim();
|
|
161
|
+
const model = (await promptQuestion(rl, `Nama Model yang ingin dipakai di 9Router (contoh: harobor): `)).trim();
|
|
164
162
|
|
|
165
163
|
settings = {
|
|
166
164
|
provider: "anthropic",
|
|
167
165
|
base_url: baseUrl.replace(/\/+$/, ""),
|
|
168
166
|
api_key: key,
|
|
169
|
-
model
|
|
167
|
+
model: model || "harobor"
|
|
170
168
|
};
|
|
171
169
|
} else if (choice === "3") {
|
|
172
170
|
const key = (await promptQuestion(rl, "Masukkan GEMINI_API_KEY: ")).trim();
|
|
173
|
-
const model = (await promptQuestion(rl, "Nama Model (gemini-3.5-flash-lite): ")).trim() || "gemini-3.5-flash-lite";
|
|
171
|
+
const model = (await promptQuestion(rl, "Nama Model (contoh: gemini-3.5-flash-lite): ")).trim() || "gemini-3.5-flash-lite";
|
|
174
172
|
settings = {
|
|
175
173
|
provider: "openai",
|
|
176
174
|
base_url: "https://generativelanguage.googleapis.com/v1beta/openai",
|
|
@@ -179,9 +177,9 @@ async function runInteractiveConfig() {
|
|
|
179
177
|
};
|
|
180
178
|
} else {
|
|
181
179
|
console.log("Contoh Base URL: https://tokenharbor.ai/v1");
|
|
182
|
-
const baseUrl = (await promptQuestion(rl, "Base URL
|
|
180
|
+
const baseUrl = (await promptQuestion(rl, "Base URL: ")).trim() || "https://tokenharbor.ai/v1";
|
|
183
181
|
const key = (await promptQuestion(rl, "API Key: ")).trim();
|
|
184
|
-
const model = (await promptQuestion(rl, "Model (deepseek-v4.1-flash:free): ")).trim() || "deepseek-v4.1-flash:free";
|
|
182
|
+
const model = (await promptQuestion(rl, "Nama Model (contoh: deepseek-v4.1-flash:free): ")).trim() || "deepseek-v4.1-flash:free";
|
|
185
183
|
settings = {
|
|
186
184
|
provider: "openai",
|
|
187
185
|
api_key: key,
|
|
@@ -236,13 +234,15 @@ function buildSystemPrompt() {
|
|
|
236
234
|
return `Kamu KILUA, AI Coding Agent otonom di terminal lokal. Folder aktif: ${process.cwd()}.
|
|
237
235
|
KEMAMPUAN TOOLS:
|
|
238
236
|
- read_file, write_file, edit_file, list_dir
|
|
239
|
-
- run_cmd: menjalankan perintah terminal lokal (npm, npx, git, node, python, build, test, curl, dsb).
|
|
237
|
+
- run_cmd: menjalankan perintah terminal lokal (npm, npx, git, node, python, build, test, curl, install skill, dsb).
|
|
240
238
|
|
|
241
|
-
ATURAN OTONOM KILUA (SELF-TESTING):
|
|
239
|
+
ATURAN OTONOM KILUA (SELF-TESTING & AUTO-INSTALL SKILL):
|
|
242
240
|
1. Jika pengguna meminta membuat project/fitur/skrip, JANGAN langsung serahkan begitu saja. Kamu HARUS mencoba atau memvalidasinya sendiri terlebih dahulu menggunakan run_cmd (misal: jalankan skrip, test, build, atau cek sintaks).
|
|
243
241
|
2. Jika ada error saat kamu mencoba, perbaiki langsung menggunakan edit_file/write_file sampai berhasil.
|
|
244
242
|
3. Setelah berhasil dicoba dan dipastikan tidak error, barulah beri tahu pengguna hasil dan cara menjalankannya.
|
|
245
|
-
4.
|
|
243
|
+
4. Jika pengguna di chat menyuruh kamu install skill (misal: "install skill vercel-labs/skills@find-skills" atau skill lain), jalankan run_cmd dengan perintah:
|
|
244
|
+
npx skills add <nama-skill> --cwd "${SKILLS_DIR}"
|
|
245
|
+
Lalu beri tahu pengguna bahwa skill tersebut telah siap dipakai.${skillsInfo}
|
|
246
246
|
|
|
247
247
|
Respon ringkas, padat, dan bertindak langsung.`;
|
|
248
248
|
}
|
|
@@ -454,11 +454,12 @@ function printHelp() {
|
|
|
454
454
|
\x1b[1m\x1b[35m=== PERINTAH SLASH KILUA (/) ===\x1b[0m
|
|
455
455
|
\x1b[36m/help\x1b[0m Lihat panduan perintah ini
|
|
456
456
|
\x1b[36m/models\x1b[0m Lihat dan ganti model AI saat ini
|
|
457
|
-
\x1b[36m/skills\x1b[0m Lihat daftar skills yang terpasang
|
|
458
|
-
\x1b[36m/install-skill\x1b[0m Pasang skill baru (misal: /install-skill vercel-labs/skills@find-skills)
|
|
457
|
+
\x1b[36m/skills\x1b[0m Lihat daftar skills yang terpasang di Kilua
|
|
459
458
|
\x1b[36m/clear\x1b[0m Bersihkan riwayat percakapan sesi ini
|
|
460
459
|
\x1b[36m/config\x1b[0m Ubah API Key, Provider, atau Base URL
|
|
461
460
|
\x1b[36m/exit\x1b[0m Keluar dari Kilua Agent
|
|
461
|
+
|
|
462
|
+
\x1b[90mTips: Untuk menginstall skill baru, cukup suruh Kilua di chat (misal: "tolong install skill find-skills")!\x1b[0m
|
|
462
463
|
`);
|
|
463
464
|
}
|
|
464
465
|
|
|
@@ -472,12 +473,12 @@ async function handleSlashCommand(cmd, settings, convo, rl) {
|
|
|
472
473
|
}
|
|
473
474
|
|
|
474
475
|
if (action === "/models" || action === "/model") {
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
console.log(
|
|
480
|
-
const newModel = (await promptQuestion(rl, `Ganti model (Enter untuk tetap '${settings.model}'): `)).trim();
|
|
476
|
+
if (!settings.base_url || !settings.api_key) {
|
|
477
|
+
console.log(`\n\x1b[33m[!] Belum terhubung ke config provider. Jalankan /config terlebih dahulu.\x1b[0m\n`);
|
|
478
|
+
return settings;
|
|
479
|
+
}
|
|
480
|
+
console.log(`\n\x1b[33mModel aktif saat ini:\x1b[0m \x1b[32m${settings.model}\x1b[0m (Provider: ${settings.base_url})`);
|
|
481
|
+
const newModel = (await promptQuestion(rl, `Ganti nama model (Enter untuk tetap '${settings.model}'): `)).trim();
|
|
481
482
|
if (newModel) {
|
|
482
483
|
settings.model = newModel;
|
|
483
484
|
saveSettings(settings);
|
|
@@ -490,8 +491,8 @@ async function handleSlashCommand(cmd, settings, convo, rl) {
|
|
|
490
491
|
const list = listInstalledSkills();
|
|
491
492
|
console.log(`\n\x1b[35m=== SKILLS TERPASANG (${SKILLS_DIR}) ===\x1b[0m`);
|
|
492
493
|
if (!list.length) {
|
|
493
|
-
console.log(`
|
|
494
|
-
console.log(`
|
|
494
|
+
console.log(`Belum ada skill tambahan terpasang.`);
|
|
495
|
+
console.log(`Suruh Kilua di chat untuk install, misal: \x1b[36m"Kilua, tolong install skill vercel-labs/skills@find-skills"\x1b[0m`);
|
|
495
496
|
} else {
|
|
496
497
|
for (const s of list) {
|
|
497
498
|
console.log(`- \x1b[32m${s.name}\x1b[0m: ${s.desc}`);
|
|
@@ -501,22 +502,6 @@ async function handleSlashCommand(cmd, settings, convo, rl) {
|
|
|
501
502
|
return settings;
|
|
502
503
|
}
|
|
503
504
|
|
|
504
|
-
if (action === "/install-skill") {
|
|
505
|
-
const target = parts.slice(1).join(" ").trim();
|
|
506
|
-
if (!target) {
|
|
507
|
-
console.log(`\x1b[33mContoh penggunaan: /install-skill vercel-labs/skills@find-skills\x1b[0m`);
|
|
508
|
-
return settings;
|
|
509
|
-
}
|
|
510
|
-
console.log(`\x1b[35m[Memasang skill ${target}...]\x1b[0m`);
|
|
511
|
-
try {
|
|
512
|
-
execSync(`npx skills add ${target}`, { cwd: SKILLS_DIR, stdio: "inherit" });
|
|
513
|
-
console.log(`\x1b[32m✓ Skill ${target} berhasil dipasang!\x1b[0m\n`);
|
|
514
|
-
} catch (e) {
|
|
515
|
-
console.error(`[!] Gagal memasang skill:`, e.message);
|
|
516
|
-
}
|
|
517
|
-
return settings;
|
|
518
|
-
}
|
|
519
|
-
|
|
520
505
|
if (action === "/clear") {
|
|
521
506
|
convo.length = 0;
|
|
522
507
|
console.clear();
|
|
@@ -545,8 +530,12 @@ async function main() {
|
|
|
545
530
|
|
|
546
531
|
let settings = loadSettings();
|
|
547
532
|
|
|
548
|
-
|
|
549
|
-
|
|
533
|
+
// Validasi ketat: jika belum ada base_url atau api_key, WAJIB setup dulu
|
|
534
|
+
const isLocalProxy = settings.base_url?.includes("127.0.0.1") || settings.base_url?.includes("localhost");
|
|
535
|
+
const hasValidConfig = settings.base_url && (settings.api_key || isLocalProxy);
|
|
536
|
+
|
|
537
|
+
if (!hasValidConfig) {
|
|
538
|
+
console.log("\x1b[33m[!] Belum ada konfigurasi AI key / provider.\x1b[0m");
|
|
550
539
|
settings = await runInteractiveConfig();
|
|
551
540
|
}
|
|
552
541
|
|
|
@@ -559,7 +548,7 @@ async function main() {
|
|
|
559
548
|
console.log("\x1b[1m\x1b[35m=== KILUA AI CLI AGENT ===\x1b[0m");
|
|
560
549
|
console.log(`CWD : \x1b[33m${process.cwd()}\x1b[0m`);
|
|
561
550
|
console.log(`Provider: \x1b[32m${settings.base_url}\x1b[0m (${settings.model})`);
|
|
562
|
-
console.log(`Config : \x1b[90m${SETTINGS_PATH}\x1b[0m (ketik \x1b[36m/help\x1b[0m untuk
|
|
551
|
+
console.log(`Config : \x1b[90m${SETTINGS_PATH}\x1b[0m (ketik \x1b[36m/help\x1b[0m untuk panduan)\n`);
|
|
563
552
|
|
|
564
553
|
let rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
565
554
|
const ask = () => {
|