@baiworcode/baiworcode 1.0.0-beta.1 → 1.0.0-beta.2
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 +451 -450
- package/bin/baiwor.js +11 -7
- package/package.json +60 -60
- package/src/auth/resolve.js +35 -0
- package/src/branding.js +26 -26
- package/src/tools/sandbox.js +2 -3
- package/src/tools/todoTool.js +43 -3
- package/src/update.js +1 -1
package/bin/baiwor.js
CHANGED
|
@@ -51,6 +51,7 @@ import { runModelMenu } from '../src/modelMenu.js';
|
|
|
51
51
|
import { handleModelCommand } from '../src/modelAlias.js';
|
|
52
52
|
import { askBaiworInput, COMMANDS } from '../src/prompt.js';
|
|
53
53
|
import { login, logout, authStatus } from '../src/auth/index.js';
|
|
54
|
+
import { hasActiveCredentials } from '../src/auth/resolve.js';
|
|
54
55
|
import { BAWOR_LOGO } from '../src/assets/baworLogo.js';
|
|
55
56
|
import { handleUserChat, resetConversation, conversationSession } from '../src/chat/index.js';
|
|
56
57
|
import {
|
|
@@ -442,8 +443,9 @@ function showBanner() {
|
|
|
442
443
|
console.log(' '.repeat(centerPadInTextLogo(layout, tagline)) + chalk.gray(tagline));
|
|
443
444
|
console.log();
|
|
444
445
|
|
|
445
|
-
const
|
|
446
|
-
const
|
|
446
|
+
const siapDipakai = hasActiveCredentials(config);
|
|
447
|
+
const readyText = siapDipakai ? '● Siap' : '○ Belum siap';
|
|
448
|
+
const readyBadge = siapDipakai ? chalk.green(readyText) : chalk.yellow(readyText);
|
|
447
449
|
// Lebar dalam kotak atas disamakan dengan garis tengah (targetWidth + 2) agar
|
|
448
450
|
// ketiga batang sejajar walau panjang nomor versi berubah.
|
|
449
451
|
const verLabel = `─ v${VERSION} `;
|
|
@@ -460,16 +462,18 @@ function showBanner() {
|
|
|
460
462
|
console.log(midBar);
|
|
461
463
|
console.log(padBox(chalk.whiteBright('Ruang Kerja & Status')));
|
|
462
464
|
console.log(padBox(chalk.gray('› ') + 'Folder Aktif : ' + chalk.cyan(process.cwd())));
|
|
463
|
-
const modelInfo =
|
|
464
|
-
? chalk.
|
|
465
|
-
:
|
|
465
|
+
const modelInfo = !siapDipakai
|
|
466
|
+
? chalk.gray('Belum siap — ketik /model')
|
|
467
|
+
: config.activeModel !== 'Not configured'
|
|
468
|
+
? chalk.hex('#F59E0B')(config.activeModel) + chalk.gray(` (${config.activeProvider})`)
|
|
469
|
+
: chalk.gray('Belum dikonfigurasi (/model)');
|
|
466
470
|
console.log(padBox(chalk.gray('› ') + 'Model Aktif : ' + modelInfo));
|
|
467
471
|
console.log(botBar);
|
|
468
472
|
console.log();
|
|
469
473
|
|
|
470
|
-
// Onboarding singkat untuk pengguna baru: tanpa
|
|
474
|
+
// Onboarding singkat untuk pengguna baru: tanpa kredensial siap, percakapan
|
|
471
475
|
// pertama pasti gagal — arahkan ke /model atau /login SEBELUM mereka bingung.
|
|
472
|
-
if (config.activeModel === 'Not configured') {
|
|
476
|
+
if (!siapDipakai || config.activeModel === 'Not configured') {
|
|
473
477
|
console.log(chalk.hex('#FBBF24').bold(' 👋 Selamat datang di bAIwor Code! Ini langkah pertamamu:'));
|
|
474
478
|
console.log(
|
|
475
479
|
chalk.white(' 1. Ketik ') +
|
package/package.json
CHANGED
|
@@ -1,60 +1,60 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@baiworcode/baiworcode",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
4
|
-
"description": "bAIwor Code [
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "bin/baiwor.js",
|
|
7
|
-
"bin": {
|
|
8
|
-
"baiworcode": "bin/baiwor.js",
|
|
9
|
-
"baiwor": "bin/baiwor.js"
|
|
10
|
-
},
|
|
11
|
-
"files": [
|
|
12
|
-
"bin",
|
|
13
|
-
"src",
|
|
14
|
-
"scripts",
|
|
15
|
-
"README.md",
|
|
16
|
-
"LICENSE"
|
|
17
|
-
],
|
|
18
|
-
"publishConfig": {
|
|
19
|
-
"access": "public",
|
|
20
|
-
"provenance": true
|
|
21
|
-
},
|
|
22
|
-
"repository": {
|
|
23
|
-
"type": "git",
|
|
24
|
-
"url": "git+https://github.com/bAIwor/baiworcode.git"
|
|
25
|
-
},
|
|
26
|
-
"homepage": "https://baiwor.my.id",
|
|
27
|
-
"bugs": {
|
|
28
|
-
"url": "https://github.com/bAIwor/baiworcode/issues"
|
|
29
|
-
},
|
|
30
|
-
"scripts": {
|
|
31
|
-
"start": "node ./bin/baiwor.js",
|
|
32
|
-
"test": "node scripts/run-tests.mjs",
|
|
33
|
-
"audit:provider": "node scripts/audit-provider.mjs",
|
|
34
|
-
"check": "npm test",
|
|
35
|
-
"prepublishOnly": "npm test"
|
|
36
|
-
},
|
|
37
|
-
"keywords": [
|
|
38
|
-
"baiwor",
|
|
39
|
-
"punakawan",
|
|
40
|
-
"cli",
|
|
41
|
-
"ai-agent",
|
|
42
|
-
"coding-agent",
|
|
43
|
-
"terminal",
|
|
44
|
-
"openai-compatible",
|
|
45
|
-
"gemini",
|
|
46
|
-
"indonesia"
|
|
47
|
-
],
|
|
48
|
-
"author": "Wijang",
|
|
49
|
-
"license": "MIT",
|
|
50
|
-
"engines": {
|
|
51
|
-
"node": ">=18"
|
|
52
|
-
},
|
|
53
|
-
"dependencies": {
|
|
54
|
-
"@clack/core": "^0.4.1",
|
|
55
|
-
"@clack/prompts": "^0.9.0",
|
|
56
|
-
"@insforge/instabox-sdk": "^0.5.3",
|
|
57
|
-
"chalk": "^5.4.1",
|
|
58
|
-
"commander": "^13.1.0"
|
|
59
|
-
}
|
|
60
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@baiworcode/baiworcode",
|
|
3
|
+
"version": "1.0.0-beta.2",
|
|
4
|
+
"description": "bAIwor Code [Beta] — Terminal AI Coding Agent · Jiwa Punakawan, Pikiran AI, Guardian Banyumas (https://baiwor.my.id)",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "bin/baiwor.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"baiworcode": "bin/baiwor.js",
|
|
9
|
+
"baiwor": "bin/baiwor.js"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"bin",
|
|
13
|
+
"src",
|
|
14
|
+
"scripts",
|
|
15
|
+
"README.md",
|
|
16
|
+
"LICENSE"
|
|
17
|
+
],
|
|
18
|
+
"publishConfig": {
|
|
19
|
+
"access": "public",
|
|
20
|
+
"provenance": true
|
|
21
|
+
},
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "git+https://github.com/bAIwor/baiworcode.git"
|
|
25
|
+
},
|
|
26
|
+
"homepage": "https://baiwor.my.id",
|
|
27
|
+
"bugs": {
|
|
28
|
+
"url": "https://github.com/bAIwor/baiworcode/issues"
|
|
29
|
+
},
|
|
30
|
+
"scripts": {
|
|
31
|
+
"start": "node ./bin/baiwor.js",
|
|
32
|
+
"test": "node scripts/run-tests.mjs",
|
|
33
|
+
"audit:provider": "node scripts/audit-provider.mjs",
|
|
34
|
+
"check": "npm test",
|
|
35
|
+
"prepublishOnly": "npm test"
|
|
36
|
+
},
|
|
37
|
+
"keywords": [
|
|
38
|
+
"baiwor",
|
|
39
|
+
"punakawan",
|
|
40
|
+
"cli",
|
|
41
|
+
"ai-agent",
|
|
42
|
+
"coding-agent",
|
|
43
|
+
"terminal",
|
|
44
|
+
"openai-compatible",
|
|
45
|
+
"gemini",
|
|
46
|
+
"indonesia"
|
|
47
|
+
],
|
|
48
|
+
"author": "Wijang",
|
|
49
|
+
"license": "MIT",
|
|
50
|
+
"engines": {
|
|
51
|
+
"node": ">=18"
|
|
52
|
+
},
|
|
53
|
+
"dependencies": {
|
|
54
|
+
"@clack/core": "^0.4.1",
|
|
55
|
+
"@clack/prompts": "^0.9.0",
|
|
56
|
+
"@insforge/instabox-sdk": "^0.5.3",
|
|
57
|
+
"chalk": "^5.4.1",
|
|
58
|
+
"commander": "^13.1.0"
|
|
59
|
+
}
|
|
60
|
+
}
|
package/src/auth/resolve.js
CHANGED
|
@@ -34,6 +34,41 @@ export function findMissingEnvRefs(value) {
|
|
|
34
34
|
return [...new Set(missing)];
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
/**
|
|
38
|
+
* Cek sinkron (tanpa jaringan) apakah provider aktif punya kredensial yang
|
|
39
|
+
* siap dipakai. Dipakai banner agar tidak menampilkan "Siap" pada pengguna
|
|
40
|
+
* baru yang belum mengisi API key.
|
|
41
|
+
*
|
|
42
|
+
* @param {Object} [config]
|
|
43
|
+
* @returns {boolean}
|
|
44
|
+
*/
|
|
45
|
+
export function hasActiveCredentials(config = getConfig()) {
|
|
46
|
+
try {
|
|
47
|
+
if (config.activeType === 'agy' || (config.activeProvider || '').toLowerCase().includes('antigravity')) {
|
|
48
|
+
// Ketersediaan CLI agy baru bisa dipastikan saat login; jangan blokir.
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
if (config.activeType === 'oauth') {
|
|
52
|
+
const prov = Object.values(PROVIDERS).find(
|
|
53
|
+
(p) => p.name.toLowerCase() === (config.activeProvider || '').toLowerCase()
|
|
54
|
+
);
|
|
55
|
+
if (!prov) return false;
|
|
56
|
+
const token = config.oauth?.[prov.id];
|
|
57
|
+
return Boolean(token && (token.accessToken || token.apiKey));
|
|
58
|
+
}
|
|
59
|
+
if (config.activeType === 'custom') {
|
|
60
|
+
const cp = (config.customProviders || []).find(
|
|
61
|
+
(c) => (c?.name || '').toLowerCase() === (config.activeProvider || '').toLowerCase()
|
|
62
|
+
);
|
|
63
|
+
if (!cp || typeof cp.apiKey !== 'string' || !cp.apiKey.trim()) return false;
|
|
64
|
+
return findMissingEnvRefs(cp.apiKey).length === 0;
|
|
65
|
+
}
|
|
66
|
+
return false;
|
|
67
|
+
} catch {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
37
72
|
/**
|
|
38
73
|
* Menghubungkan kredensial provider aktif (Custom API Key atau OAuth Bearer Token)
|
|
39
74
|
* Disiapkan untuk eksekusi chat streaming pada Tahap 3A.
|
package/src/branding.js
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Identitas resmi bAIwor Code.
|
|
3
|
-
*
|
|
4
|
-
* Semua nama, versi, tautan, dan User-Agent dikumpulkan di satu tempat supaya
|
|
5
|
-
* branding baiwor.my.id konsisten di seluruh aplikasi. Sebelumnya versi dan
|
|
6
|
-
* User-Agent ditulis ulang di banyak berkas, sehingga satu perubahan versi
|
|
7
|
-
* berisiko meninggalkan sisa yang basi.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
export const APP_NAME = 'bAIwor Code';
|
|
11
|
-
export const APP_SLUG = 'baiworcode';
|
|
12
|
-
export const VERSION = '1.0.0-beta.
|
|
13
|
-
|
|
14
|
-
/** Situs resmi & kanal bonus token/credit. */
|
|
15
|
-
export const WEBSITE = 'https://baiwor.my.id';
|
|
16
|
-
export const BONUS_WEBSITE = 'https://agentik.my.id';
|
|
17
|
-
|
|
18
|
-
/** User-Agent untuk panggilan API (OpenAI-compatible & OAuth). */
|
|
19
|
-
export const USER_AGENT = `${APP_NAME.replace(/\s+/g, '-')}/${VERSION}`;
|
|
20
|
-
export const CLI_USER_AGENT = `bAIwor-cli/${VERSION}`;
|
|
21
|
-
|
|
22
|
-
/** Tagline resmi (filosofi Punakawan Banyumasan). */
|
|
23
|
-
export const TAGLINE = 'Saka Bawor dadi bAIwor — Jiwa Punakawan, Pikiran AI, Guardian Banyumas';
|
|
24
|
-
|
|
25
|
-
/** Nama badan hukum di balik bAIwor Code (tampil di banner & pesan keluar). */
|
|
26
|
-
export const COMPANY = 'PT. bAIwor Agentic Indonesia';
|
|
1
|
+
/**
|
|
2
|
+
* Identitas resmi bAIwor Code.
|
|
3
|
+
*
|
|
4
|
+
* Semua nama, versi, tautan, dan User-Agent dikumpulkan di satu tempat supaya
|
|
5
|
+
* branding baiwor.my.id konsisten di seluruh aplikasi. Sebelumnya versi dan
|
|
6
|
+
* User-Agent ditulis ulang di banyak berkas, sehingga satu perubahan versi
|
|
7
|
+
* berisiko meninggalkan sisa yang basi.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export const APP_NAME = 'bAIwor Code';
|
|
11
|
+
export const APP_SLUG = 'baiworcode';
|
|
12
|
+
export const VERSION = '1.0.0-beta.2';
|
|
13
|
+
|
|
14
|
+
/** Situs resmi & kanal bonus token/credit. */
|
|
15
|
+
export const WEBSITE = 'https://baiwor.my.id';
|
|
16
|
+
export const BONUS_WEBSITE = 'https://agentik.my.id';
|
|
17
|
+
|
|
18
|
+
/** User-Agent untuk panggilan API (OpenAI-compatible & OAuth). */
|
|
19
|
+
export const USER_AGENT = `${APP_NAME.replace(/\s+/g, '-')}/${VERSION}`;
|
|
20
|
+
export const CLI_USER_AGENT = `bAIwor-cli/${VERSION}`;
|
|
21
|
+
|
|
22
|
+
/** Tagline resmi (filosofi Punakawan Banyumasan). */
|
|
23
|
+
export const TAGLINE = 'Saka Bawor dadi bAIwor — Jiwa Punakawan, Pikiran AI, Guardian Banyumas';
|
|
24
|
+
|
|
25
|
+
/** Nama badan hukum di balik bAIwor Code (tampil di banner & pesan keluar). */
|
|
26
|
+
export const COMPANY = 'PT. bAIwor Agentic Indonesia';
|
package/src/tools/sandbox.js
CHANGED
|
@@ -222,8 +222,7 @@ export function isPathAllowed(targetPath, workspace = process.cwd()) {
|
|
|
222
222
|
if (isSubPath(workspace, resolved)) return true;
|
|
223
223
|
if (isSubPath(os.tmpdir(), resolved)) return true;
|
|
224
224
|
|
|
225
|
-
|
|
226
|
-
return SYSTEM_ALLOWED_PREFIXES.some((prefix) => lower === prefix || lower.startsWith(prefix));
|
|
225
|
+
return SYSTEM_ALLOWED_PREFIXES.some((prefix) => isSubPath(prefix, resolved));
|
|
227
226
|
}
|
|
228
227
|
|
|
229
228
|
/**
|
|
@@ -305,7 +304,7 @@ function isOutsideWorkspace(candidate, workspace) {
|
|
|
305
304
|
|
|
306
305
|
const lower = path.win32.resolve(candidate).toLowerCase();
|
|
307
306
|
const isSystem = WIN32_SYSTEM_PREFIXES.some(
|
|
308
|
-
(prefix) => lower === prefix || lower.startsWith(prefix)
|
|
307
|
+
(prefix) => lower === prefix || lower.startsWith(prefix + '\\')
|
|
309
308
|
);
|
|
310
309
|
if (isSystem) return false;
|
|
311
310
|
|
package/src/tools/todoTool.js
CHANGED
|
@@ -219,6 +219,42 @@ function summarize(items) {
|
|
|
219
219
|
return summary;
|
|
220
220
|
}
|
|
221
221
|
|
|
222
|
+
/**
|
|
223
|
+
* Menormalkan bentuk `todos` yang dikirim model. Model kadang membungkus daftar
|
|
224
|
+
* (`{ "item": [...] }`), mengirim satu objek tugas, atau memakai peta id→tugas,
|
|
225
|
+
* dan mengirim `merge` sebagai string. Bentuk-bentuk ini diartikan alih-alih
|
|
226
|
+
* langsung ditolak, tanpa melonggarkan validasi isi tiap tugas.
|
|
227
|
+
*
|
|
228
|
+
* @param {unknown} todos
|
|
229
|
+
* @returns {Array|null} null bila tidak bisa diartikan sebagai daftar tugas.
|
|
230
|
+
*/
|
|
231
|
+
export function coerceTodosInput(todos) {
|
|
232
|
+
if (Array.isArray(todos)) return todos;
|
|
233
|
+
if (!todos || typeof todos !== 'object') return null;
|
|
234
|
+
|
|
235
|
+
for (const key of ['item', 'items', 'todos', 'list', 'data', 'tasks']) {
|
|
236
|
+
if (Array.isArray(todos[key])) return todos[key];
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
if (typeof todos.content === 'string' || typeof todos.id === 'string') return [todos];
|
|
240
|
+
|
|
241
|
+
const values = Object.values(todos);
|
|
242
|
+
if (
|
|
243
|
+
values.length > 0 &&
|
|
244
|
+
values.every(
|
|
245
|
+
(v) => v && typeof v === 'object' && (typeof v.content === 'string' || typeof v.id === 'string')
|
|
246
|
+
)
|
|
247
|
+
) {
|
|
248
|
+
return values;
|
|
249
|
+
}
|
|
250
|
+
return null;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/** `merge` bisa datang sebagai boolean atau string "true"/"1". */
|
|
254
|
+
function coerceMerge(merge) {
|
|
255
|
+
return merge === true || merge === 'true' || merge === 1 || merge === '1';
|
|
256
|
+
}
|
|
257
|
+
|
|
222
258
|
/**
|
|
223
259
|
* Handler tool `todo_list`.
|
|
224
260
|
*
|
|
@@ -240,12 +276,16 @@ export async function handleTodoList({ todos, merge = false } = {}) {
|
|
|
240
276
|
};
|
|
241
277
|
}
|
|
242
278
|
|
|
243
|
-
|
|
244
|
-
|
|
279
|
+
const daftar = coerceTodosInput(todos);
|
|
280
|
+
if (!daftar) {
|
|
281
|
+
return {
|
|
282
|
+
success: false,
|
|
283
|
+
output: `Error: "todos" harus berupa array tugas, diterima ${typeof todos}. Kirim daftar seperti [{"id":"1","content":"...","status":"pending"}].`,
|
|
284
|
+
};
|
|
245
285
|
}
|
|
246
286
|
|
|
247
287
|
try {
|
|
248
|
-
const items = todoStore.write(
|
|
288
|
+
const items = todoStore.write(daftar, coerceMerge(merge));
|
|
249
289
|
return {
|
|
250
290
|
success: true,
|
|
251
291
|
output: JSON.stringify(
|
package/src/update.js
CHANGED
|
@@ -33,7 +33,7 @@ export async function runUpdate(options = {}) {
|
|
|
33
33
|
|
|
34
34
|
if (!isGit) {
|
|
35
35
|
console.log(theme.warning(' ⚠️ Instalasi bAIwor Code ini tidak dijalankan dari repositori Git.'));
|
|
36
|
-
console.log(theme.muted(' Gunakan `npm update -g baiworcode` untuk pembaruan paket npm.\n'));
|
|
36
|
+
console.log(theme.muted(' Gunakan `npm update -g @baiworcode/baiworcode` untuk pembaruan paket npm.\n'));
|
|
37
37
|
return { updated: false, message: 'Non-git installation' };
|
|
38
38
|
}
|
|
39
39
|
|