kiosapi 0.1.6 → 0.1.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/dist/session.js CHANGED
@@ -1,13 +1,18 @@
1
- import { newSession, resetSession, runTurn } from './agent/run.js';
2
- import { runTeam } from './agent/team.js';
3
- import { resolveModel } from './api.js';
4
- import { cmdGambar, cmdIsi, cmdLihat, cmdMasuk, cmdPakai, cmdSaldo, cmdVideo, maybeNotifyUpdate, pickModel, warnIfNoTools, } from './commands.js';
5
- import { loadConfig } from './config.js';
6
- import { bold, cyan, dim, green, prompt, red } from './ui.js';
1
+ import { spawnSync } from 'node:child_process';
2
+ import { clearCheckpoint, loadCheckpoint, newSession, resetSession, runTurn, undoLastTurn, } from './agent/run.js';
3
+ import { runCustomTeam, runTeam } from './agent/team.js';
4
+ import { expandAtMentions } from './agent/tools.js';
5
+ import { resolveModel, streamChat } from './api.js';
6
+ import { cmdGambar, cmdIsi, cmdLihat, cmdMasuk, cmdPakai, cmdPerbarui, cmdSaldo, cmdVideo, maybeNotifyUpdate, pickModel, warnIfNoTools, } from './commands.js';
7
+ import { listTeamConfigs, loadConfig, loadProjectConfig, loadTeamConfig, saveTeamConfig, } from './config.js';
8
+ import { bold, cyan, dim, green, idn, prompt, red, thinking, yellow } from './ui.js';
7
9
  const MODES = ['rencana', 'edit', 'buat'];
8
- /** The prompt indicator shows the active mode (and ⚡ when auto-approve is on). */
10
+ /** The prompt indicator shows the active mode, turn count, accumulated tokens, and ⚡ for auto. */
9
11
  function label(s) {
10
- return `${cyan(`${s.mode}${s.otomatis ? ' ⚡' : ''}`)} › `;
12
+ const turns = s.messages.filter((m) => m.role === 'user').length;
13
+ const ctx = turns > 0 ? dim(` [${turns}]`) : '';
14
+ const tok = s.totalTokens > 0 ? dim(` ${idn(s.totalTokens)}tok`) : '';
15
+ return `${cyan(`${s.mode}${s.otomatis ? ' ⚡' : ''}`) + ctx + tok} › `;
11
16
  }
12
17
  function banner(s) {
13
18
  console.log(`${bold('Kiosapi CLI')} — sesi interaktif
@@ -18,20 +23,32 @@ ${dim('Ketik tugasmu langsung. Perintah meta diawali "/". /bantuan untuk daftar,
18
23
  }
19
24
  function slashHelp() {
20
25
  console.log(`${bold('Perintah sesi:')}
21
- /tim <tugas> Multi-agen (perencana→pengkode→peninjau)
22
- /peran [peran] [model] Atur model per peran tim (atau lihat/reset)
23
- /gambar <prompt> Buat gambar file
24
- /video <prompt> Buat video file
25
- /lihat <file> <pertanyaan> Tanya model vision tentang gambar
26
- /mode [rencana|edit|buat] Lihat/ubah mode agen
27
- /model [id|filter] Pilih model (tanpa argumen = daftar bernomor)
28
- /otomatis Hidup/matikan auto-approve (lewati konfirmasi)
29
- /bersih Bersihkan riwayat percakapan
30
- /saldo Lihat saldo
31
- /pakai [--hari N] Ringkasan pemakaian
32
- /isi <jumlah> Buat tagihan top-up
33
- /bantuan Tampilkan bantuan ini
34
- /keluar Keluar dari sesi`);
26
+ /tim <tugas> Multi-agen bawaan (perencana→pengkode→peninjau)
27
+ /tim --pakai <nama> <tugas> Jalankan tim kustom tersimpan
28
+ /peran [peran] [model] Atur model per peran tim (atau lihat/reset)
29
+ /simpan-tim <nama> Simpan konfigurasi /peran saat ini sebagai tim kustom
30
+ /tim-daftar Lihat semua tim kustom tersimpan
31
+ /gambar <prompt> Buat gambar → file
32
+ /video <prompt> Buat video file
33
+ /lihat <file> <pertanyaan> Tanya model vision tentang gambar
34
+ /mode [rencana|edit|buat] Lihat/ubah mode agen
35
+ /model [id|filter] Pilih model (tanpa argumen = daftar bernomor)
36
+ /otomatis Hidup/matikan auto-approve (lewati konfirmasi)
37
+ /commit [--all] Buat pesan commit (model) dari git diff → konfirmasi → commit
38
+ /diff [--staged|<ref>] Tampilkan git diff langsung (tanpa kirim ke model)
39
+ /shell <perintah> Jalankan perintah langsung tanpa agent (tidak konsumsi token)
40
+ /undo Batalkan giliran terakhir (hapus dari riwayat)
41
+ /ringkas Padatkan riwayat sesi menjadi ringkasan singkat
42
+ /bersih Bersihkan riwayat percakapan & checkpoint
43
+ /lanjut Lanjutkan sesi dari checkpoint terakhir
44
+ /perbarui Update CLI ke versi terbaru (tanpa keluar sesi)
45
+ /saldo Lihat saldo
46
+ /pakai [--hari N] Ringkasan pemakaian
47
+ /isi <jumlah> Buat tagihan top-up
48
+ /bantuan Tampilkan bantuan ini
49
+ /keluar Keluar dari sesi
50
+
51
+ ${dim('Tips: @path/file.ts menyertakan file · @git:diff / @git:status / @git:log menyertakan output git.')}`);
35
52
  }
36
53
  /** Handle a /slash command. Returns true when the session should end. */
37
54
  async function runSlash(line, s) {
@@ -83,7 +100,165 @@ async function runSlash(line, s) {
83
100
  return false;
84
101
  case 'bersih':
85
102
  resetSession(s);
86
- console.log(dim('Riwayat dibersihkan.'));
103
+ clearCheckpoint();
104
+ console.log(dim('Riwayat dan checkpoint dibersihkan.'));
105
+ return false;
106
+ case 'commit': {
107
+ const allFlag = rest[0] === '--all' || rest[0] === '-a';
108
+ const cwd = process.cwd();
109
+ if (allFlag)
110
+ spawnSync('git', ['add', '-A'], { cwd, encoding: 'utf8' });
111
+ const stagedOut = spawnSync('git', ['diff', '--staged'], { cwd, encoding: 'utf8' });
112
+ let diff = (stagedOut.stdout ?? '').trim();
113
+ if (!diff) {
114
+ const statusOut = spawnSync('git', ['status', '--short'], { cwd, encoding: 'utf8' });
115
+ const changes = (statusOut.stdout ?? '').trim();
116
+ if (!changes) {
117
+ console.log(dim('Tidak ada perubahan untuk di-commit.'));
118
+ }
119
+ else {
120
+ console.log(yellow('Tidak ada yang di-stage. Gunakan /commit --all untuk stage semua.'));
121
+ console.log(dim(changes));
122
+ }
123
+ return false;
124
+ }
125
+ if (diff.length > 8000)
126
+ diff = `${diff.slice(0, 8000)}\n…[dipotong]`;
127
+ console.log(dim('Menganalisa diff…'));
128
+ const stop = thinking();
129
+ let commitMsg = '';
130
+ let commitPrinted = false;
131
+ try {
132
+ for await (const piece of streamChat(s.model, [
133
+ {
134
+ role: 'system',
135
+ content: 'Write ONLY a git commit message (no backticks, no preamble). Subject ≤72 chars, imperative English ("add", "fix", "update"). Optional body after blank line for complex changes.',
136
+ },
137
+ { role: 'user', content: `Write a commit message for this diff:\n\n${diff}` },
138
+ ])) {
139
+ if (!commitPrinted) {
140
+ stop();
141
+ commitPrinted = true;
142
+ }
143
+ process.stdout.write(piece);
144
+ commitMsg += piece;
145
+ }
146
+ }
147
+ finally {
148
+ if (!commitPrinted)
149
+ stop();
150
+ }
151
+ if (commitMsg)
152
+ process.stdout.write('\n\n');
153
+ commitMsg = commitMsg
154
+ .trim()
155
+ .replace(/^```[\w]*\n?/gm, '')
156
+ .replace(/^```$/gm, '')
157
+ .trim();
158
+ if (!commitMsg) {
159
+ console.log(red('Gagal generate pesan commit.'));
160
+ return false;
161
+ }
162
+ const ans = (await prompt('Commit? [Enter=ya · e=edit · t=tidak] ')).trim().toLowerCase();
163
+ if (ans === 't' || ans === 'tidak') {
164
+ console.log(dim('Dibatalkan.'));
165
+ return false;
166
+ }
167
+ if (ans === 'e' || ans === 'edit') {
168
+ const manual = (await prompt('Pesan commit: ')).trim();
169
+ if (!manual) {
170
+ console.log(dim('Dibatalkan.'));
171
+ return false;
172
+ }
173
+ commitMsg = manual;
174
+ }
175
+ const res = spawnSync('git', ['commit', '-m', commitMsg], { cwd, encoding: 'utf8' });
176
+ if (res.status === 0) {
177
+ console.log(green(`✓ ${(res.stdout ?? '').trim()}`));
178
+ }
179
+ else {
180
+ console.log(red(`Git error: ${((res.stderr ?? '') || (res.stdout ?? '')).trim()}`));
181
+ }
182
+ return false;
183
+ }
184
+ case 'undo':
185
+ case 'batalkan': {
186
+ if (undoLastTurn(s)) {
187
+ clearCheckpoint();
188
+ const turns = s.messages.filter((m) => m.role === 'user').length;
189
+ console.log(dim(`Giliran terakhir dibatalkan. Sisa: ${turns} giliran.`));
190
+ }
191
+ else {
192
+ console.log(dim('Tidak ada giliran untuk dibatalkan.'));
193
+ }
194
+ return false;
195
+ }
196
+ case 'ringkas': {
197
+ const textMsgs = s.messages.filter((m) => (m.role === 'user' || m.role === 'assistant') &&
198
+ typeof m.content === 'string' &&
199
+ m.content.trim().length > 0);
200
+ if (textMsgs.length === 0) {
201
+ console.log(dim('Belum ada percakapan untuk diringkas.'));
202
+ return false;
203
+ }
204
+ console.log(dim('Meringkas konteks sesi…'));
205
+ const stop = thinking();
206
+ let summary = '';
207
+ let printed = false;
208
+ try {
209
+ for await (const piece of streamChat(s.model, [
210
+ ...textMsgs,
211
+ {
212
+ role: 'user',
213
+ content: 'Buat ringkasan singkat (max 5 poin) dari semua yang sudah dikerjakan. Fokus pada file yang diubah dan keputusan penting. Format: daftar bullet Bahasa Indonesia.',
214
+ },
215
+ ])) {
216
+ if (!printed) {
217
+ stop();
218
+ printed = true;
219
+ }
220
+ process.stdout.write(piece);
221
+ summary += piece;
222
+ }
223
+ }
224
+ finally {
225
+ if (!printed)
226
+ stop();
227
+ }
228
+ if (summary)
229
+ process.stdout.write('\n');
230
+ if (!summary) {
231
+ console.log(red('Gagal membuat ringkasan.'));
232
+ return false;
233
+ }
234
+ // Replace the conversation body with the condensed summary
235
+ const systemMsg = s.messages[0];
236
+ s.messages = [
237
+ systemMsg,
238
+ { role: 'user', content: `Ringkasan sesi sejauh ini:\n${summary}` },
239
+ { role: 'assistant', content: 'Mengerti, saya akan melanjutkan dari titik ini.' },
240
+ ];
241
+ clearCheckpoint();
242
+ console.log(dim('\n✓ Konteks dipadatkan menjadi 3 pesan. Lanjutkan dengan instruksi berikutnya.'));
243
+ return false;
244
+ }
245
+ case 'lanjut':
246
+ case 'resume': {
247
+ const cp = loadCheckpoint();
248
+ if (!cp) {
249
+ console.log(dim('Tidak ada checkpoint tersimpan.'));
250
+ }
251
+ else {
252
+ const when = new Date(cp.savedAt).toLocaleString('id-ID');
253
+ const turns = cp.messages.filter((m) => m.role === 'user').length;
254
+ console.log(dim(`Checkpoint: ${cp.mode} · ${turns} giliran · ${when}`));
255
+ console.log(dim('Untuk melanjutkan, keluar sesi lalu jalankan: kiosapi lanjut'));
256
+ }
257
+ return false;
258
+ }
259
+ case 'perbarui':
260
+ case 'update':
261
+ await cmdPerbarui();
87
262
  return false;
88
263
  case 'saldo':
89
264
  await cmdSaldo();
@@ -96,18 +271,87 @@ async function runSlash(line, s) {
96
271
  return false;
97
272
  case 'tim':
98
273
  case 'team': {
99
- const task = rest.join(' ').trim();
100
- if (!task)
101
- console.log(red('Beri tugas. Contoh: /tim bikin endpoint /health + tes'));
102
- else
103
- await runTeam(task, {
104
- models: {
105
- perencana: s.teamModels.perencana ?? s.model,
106
- pengkode: s.teamModels.pengkode ?? s.model,
107
- peninjau: s.teamModels.peninjau ?? s.model,
274
+ // /tim --pakai <nama> <tugas> or /tim <tugas>
275
+ if (rest[0] === '--pakai') {
276
+ const configName = rest[1]?.trim();
277
+ const task = rest.slice(2).join(' ').trim();
278
+ if (!configName) {
279
+ console.log(red('Beri nama tim. Contoh: /tim --pakai backend-team "tambah endpoint"'));
280
+ return false;
281
+ }
282
+ if (!task) {
283
+ console.log(red('Beri tugas. Contoh: /tim --pakai backend-team "tambah endpoint"'));
284
+ return false;
285
+ }
286
+ const config = loadTeamConfig(configName);
287
+ if (!config) {
288
+ console.log(red(`Tim "${configName}" tidak ditemukan. Lihat: /tim-daftar`));
289
+ return false;
290
+ }
291
+ await runCustomTeam(task, { config, otomatis: s.otomatis });
292
+ }
293
+ else {
294
+ const task = rest.join(' ').trim();
295
+ if (!task)
296
+ console.log(red('Beri tugas. Contoh: /tim bikin endpoint /health + tes'));
297
+ else
298
+ await runTeam(task, {
299
+ models: {
300
+ perencana: s.teamModels.perencana ?? s.model,
301
+ pengkode: s.teamModels.pengkode ?? s.model,
302
+ peninjau: s.teamModels.peninjau ?? s.model,
303
+ },
304
+ otomatis: s.otomatis,
305
+ });
306
+ }
307
+ return false;
308
+ }
309
+ case 'simpan-tim': {
310
+ const nama = rest[0]?.trim();
311
+ if (!nama) {
312
+ console.log(red('Beri nama. Contoh: /simpan-tim backend-team'));
313
+ return false;
314
+ }
315
+ const config = {
316
+ nama,
317
+ peran: {
318
+ perencana: {
319
+ model: s.teamModels.perencana ?? s.model,
320
+ mode: 'rencana',
321
+ brief: 'Peranmu: PERENCANA. Telusuri kode dan susun rencana langkah yang jelas. JANGAN menulis kode.',
108
322
  },
109
- otomatis: s.otomatis,
110
- });
323
+ pengkode: {
324
+ model: s.teamModels.pengkode ?? s.model,
325
+ mode: 'buat',
326
+ brief: 'Peranmu: PENGKODE. Implementasikan tugas mengikuti rencana. Panggil selesai jika sudah.',
327
+ },
328
+ peninjau: {
329
+ model: s.teamModels.peninjau ?? s.model,
330
+ mode: 'rencana',
331
+ brief: 'Peranmu: PENINJAU. Tinjau hasil implementasi: sebutkan masalah dan saran perbaikan.',
332
+ },
333
+ },
334
+ alur: ['perencana', 'pengkode', 'peninjau'],
335
+ };
336
+ saveTeamConfig(config);
337
+ console.log(green(`✓ Tim "${nama}" tersimpan.`));
338
+ console.log(dim(` Edit di: ~/.kiosapi/tim/${nama}.json`));
339
+ console.log(dim(` Gunakan: /tim --pakai ${nama} "tugas" atau kiosapi tim --pakai ${nama} "tugas"`));
340
+ return false;
341
+ }
342
+ case 'tim-daftar': {
343
+ const teams = listTeamConfigs();
344
+ if (teams.length === 0) {
345
+ console.log(dim('Belum ada tim tersimpan. Buat dengan: /simpan-tim <nama>'));
346
+ }
347
+ else {
348
+ console.log(bold('Tim tersimpan:'));
349
+ for (const t of teams) {
350
+ const cfg = loadTeamConfig(t);
351
+ const alur = cfg?.alur.join(' → ') ?? '?';
352
+ console.log(` ${cyan(t)} ${dim(`(${alur})`)}`);
353
+ }
354
+ }
111
355
  return false;
112
356
  }
113
357
  case 'peran': {
@@ -147,6 +391,30 @@ async function runSlash(line, s) {
147
391
  case 'lihat':
148
392
  await cmdLihat(rest);
149
393
  return false;
394
+ case 'diff': {
395
+ const diffArgs = rest.length > 0 ? rest : ['HEAD'];
396
+ spawnSync('git', ['diff', '--color=always', ...diffArgs], {
397
+ cwd: process.cwd(),
398
+ stdio: 'inherit',
399
+ timeout: 10_000,
400
+ });
401
+ return false;
402
+ }
403
+ case 'shell':
404
+ case 'sh': {
405
+ const shellCmd = rest.join(' ').trim();
406
+ if (!shellCmd) {
407
+ console.log(red('Beri perintah. Contoh: /shell npm test'));
408
+ return false;
409
+ }
410
+ spawnSync(shellCmd, {
411
+ cwd: process.cwd(),
412
+ shell: true,
413
+ stdio: 'inherit',
414
+ timeout: 120_000,
415
+ });
416
+ return false;
417
+ }
150
418
  default:
151
419
  console.log(red(`Perintah tidak dikenal: /${cmd} (coba /bantuan)`));
152
420
  return false;
@@ -157,26 +425,8 @@ async function runSlash(line, s) {
157
425
  return false;
158
426
  }
159
427
  }
160
- /**
161
- * Interactive session (Claude-Code-style): run `kiosapi` with no args to enter. Plain text is a
162
- * prompt to the agent (with persistent context); `/command` runs a meta command. Logs in first if
163
- * needed.
164
- */
165
- export async function startSession() {
166
- if (!loadConfig().apiKey) {
167
- console.log(dim('Belum masuk — masukkan API key dulu.'));
168
- await cmdMasuk();
169
- if (!loadConfig().apiKey)
170
- return;
171
- }
172
- await maybeNotifyUpdate();
173
- const model = await resolveModel(undefined);
174
- const s = newSession(model, 'buat', false);
175
- banner(s);
176
- await warnIfNoTools(model);
177
- // One readline at a time: each turn uses prompt() (create+close), and slash commands that need
178
- // their own input (e.g. /model picker, masuk) also use prompt(). A persistent interface here would
179
- // collide with those → double-echoed input and a stray close that exits the session.
428
+ /** Shared interactive loop — called by both startSession and resumeFromCheckpoint. */
429
+ async function runSessionLoop(s) {
180
430
  while (true) {
181
431
  let line;
182
432
  try {
@@ -193,7 +443,7 @@ export async function startSession() {
193
443
  continue;
194
444
  }
195
445
  try {
196
- await runTurn(s, line);
446
+ await runTurn(s, expandAtMentions(line));
197
447
  }
198
448
  catch (err) {
199
449
  console.error(red(err instanceof Error ? err.message : String(err)));
@@ -201,3 +451,91 @@ export async function startSession() {
201
451
  }
202
452
  console.log(green('Sampai jumpa.'));
203
453
  }
454
+ /**
455
+ * Interactive session (Claude-Code-style): run `kiosapi` with no args to enter. Plain text is a
456
+ * prompt to the agent (with persistent context); `/command` runs a meta command. Logs in first if
457
+ * needed.
458
+ */
459
+ export async function startSession() {
460
+ if (!loadConfig().apiKey) {
461
+ console.log(dim('Belum masuk — masukkan API key dulu.'));
462
+ await cmdMasuk();
463
+ if (!loadConfig().apiKey)
464
+ return;
465
+ }
466
+ await maybeNotifyUpdate();
467
+ const proj = loadProjectConfig();
468
+ if (proj) {
469
+ const parts = [
470
+ proj.model && `model=${proj.model}`,
471
+ proj.mode && `mode=${proj.mode}`,
472
+ proj.otomatis && 'otomatis',
473
+ ].filter(Boolean);
474
+ console.log(dim(`(kiosapi.json: ${parts.join(' · ')})`));
475
+ }
476
+ const model = await resolveModel(proj?.model ?? undefined);
477
+ const s = newSession(model, proj?.mode ?? 'buat', proj?.otomatis ?? false);
478
+ if (proj?.maxSteps)
479
+ s.maxSteps = proj.maxSteps;
480
+ if (proj?.projectContext) {
481
+ const sys = s.messages[0];
482
+ sys.content += `\n\n## Konteks Proyek\n${proj.projectContext}`;
483
+ }
484
+ banner(s);
485
+ await warnIfNoTools(model);
486
+ await runSessionLoop(s);
487
+ }
488
+ /**
489
+ * Resume a checkpointed session interactively: load the saved state, show a preamble, ask for a
490
+ * continuation instruction, then drop into the full session loop (unlike cmdLanjut which only runs
491
+ * one turn and exits).
492
+ */
493
+ export async function resumeFromCheckpoint(args) {
494
+ await maybeNotifyUpdate();
495
+ const cp = loadCheckpoint();
496
+ if (!cp) {
497
+ throw new Error('Tidak ada sesi tersimpan. Mulai dengan: kiosapi buat "tugas"\n' +
498
+ 'Checkpoint disimpan otomatis setiap langkah agen.');
499
+ }
500
+ if (!loadConfig().apiKey) {
501
+ console.log(dim('Belum masuk — masukkan API key dulu.'));
502
+ await cmdMasuk();
503
+ if (!loadConfig().apiKey)
504
+ return;
505
+ }
506
+ console.log(bold('Melanjutkan sesi tersimpan'));
507
+ console.log(` Model : ${cp.model}`);
508
+ console.log(` Mode : ${cp.mode}`);
509
+ console.log(` Disimpan : ${new Date(cp.savedAt).toLocaleString('id-ID')}`);
510
+ console.log(` Direktori: ${cp.cwd}`);
511
+ if (cp.cwd !== process.cwd()) {
512
+ console.log(yellow('\n⚠ Sesi ini disimpan di direktori berbeda:'));
513
+ console.log(` ${cp.cwd}`);
514
+ const ans = (await prompt('Lanjutkan di direktori saat ini? (y/t) ')).trim().toLowerCase();
515
+ if (ans !== 'y' && ans !== 'ya')
516
+ return;
517
+ }
518
+ // Show last few turns as context
519
+ const history = cp.messages.filter((m) => m.role === 'user' || m.role === 'assistant');
520
+ const recent = history.slice(-4);
521
+ if (recent.length > 0) {
522
+ console.log(dim('\nKonteks terakhir:'));
523
+ for (const m of recent) {
524
+ const content = typeof m.content === 'string' ? m.content : '(tool calls)';
525
+ const snippet = content.trim().slice(0, 120).replace(/\n/g, ' ');
526
+ console.log(dim(` [${m.role}] ${snippet}${content.length > 120 ? '…' : ''}`));
527
+ }
528
+ }
529
+ console.log('');
530
+ const firstInstruction = args.join(' ').trim() ||
531
+ (await prompt('Instruksi lanjutan (Enter = lanjutkan): ')).trim() ||
532
+ 'Lanjutkan dari titik terakhir. Tinjau apa yang sudah dikerjakan dan selesaikan jika belum.';
533
+ // Run first turn on the restored session, then enter the full interactive loop
534
+ try {
535
+ await runTurn(cp, firstInstruction);
536
+ }
537
+ catch (err) {
538
+ console.error(red(err instanceof Error ? err.message : String(err)));
539
+ }
540
+ await runSessionLoop(cp);
541
+ }
package/dist/ui.js CHANGED
@@ -25,6 +25,11 @@ export const THINKING_TIPS = [
25
25
  'kiosapi sambung aider — pakai Kiosapi di tool agen lain.',
26
26
  '.kiosapiignore melindungi file (mis. rahasia) dari agen.',
27
27
  '/saldo & /pakai untuk cek saldo dan pemakaian.',
28
+ 'Ketik @path/file.ts dalam pesan untuk menyertakan isi file ke konteks.',
29
+ '/simpan-tim <nama> menyimpan konfigurasi peran tim saat ini.',
30
+ 'kiosapi lanjut melanjutkan sesi agen yang terputus.',
31
+ 'kiosapi tim --pakai <nama> "tugas" menjalankan tim kustom tersimpan.',
32
+ 'kiosapi tim --daftar menampilkan semua tim tersimpan.',
28
33
  ];
29
34
  const SPINNER = ['|', '/', '-', '\\'];
30
35
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kiosapi",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "type": "module",
5
5
  "description": "CLI Kiosapi.id berbahasa Indonesia — bangun aplikasimu pakai API key Kiosapi (agen + multimodal).",
6
6
  "keywords": [
@@ -28,10 +28,7 @@
28
28
  "bin": {
29
29
  "kiosapi": "./dist/index.js"
30
30
  },
31
- "files": [
32
- "dist",
33
- "README.md"
34
- ],
31
+ "files": ["dist", "README.md"],
35
32
  "engines": {
36
33
  "node": ">=20"
37
34
  },