@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/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 readyText = '● Siap';
446
- const readyBadge = chalk.green(readyText);
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 = config.activeModel !== 'Not configured'
464
- ? chalk.hex('#F59E0B')(config.activeModel) + chalk.gray(` (${config.activeProvider})`)
465
- : chalk.gray('Belum dikonfigurasi (/model)');
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 model aktif, percakapan
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.1",
4
- "description": "bAIwor Code [Alpha] — 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
- }
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
+ }
@@ -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.1';
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';
@@ -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
- const lower = resolved.toLowerCase();
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
 
@@ -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
- if (!Array.isArray(todos)) {
244
- return { success: false, output: `Error: "todos" harus berupa array, diterima ${typeof todos}.` };
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(todos, Boolean(merge));
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