@stevederico/dotbot 0.25.0 → 0.26.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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ 0.26
2
+
3
+ Update REPL prompt style
4
+ Add visible thinking output
5
+ Add /help, /show, /bye commands
6
+ Add multi-line input mode
7
+
1
8
  0.25
2
9
 
3
10
  Add delete subcommands for memory, jobs, tasks, sessions
package/bin/dotbot.js CHANGED
@@ -331,8 +331,8 @@ async function runChat(message, options) {
331
331
  ...storesObj,
332
332
  };
333
333
 
334
- process.stdout.write('\n[thinking] ');
335
- startSpinner();
334
+ let isThinking = false;
335
+ let thinkingDone = false;
336
336
 
337
337
  for await (const event of agentLoop({
338
338
  model: options.model,
@@ -343,14 +343,28 @@ async function runChat(message, options) {
343
343
  })) {
344
344
  switch (event.type) {
345
345
  case 'thinking':
346
- // Already showing spinner, ignore thinking events
346
+ if (!isThinking) {
347
+ process.stdout.write('Thinking...\n');
348
+ isThinking = true;
349
+ }
350
+ if (event.text) {
351
+ process.stdout.write(event.text);
352
+ }
347
353
  break;
348
354
  case 'text_delta':
349
- stopSpinner(''); // Stop thinking spinner silently
355
+ if (isThinking && !thinkingDone) {
356
+ stopSpinner('');
357
+ process.stdout.write('\n...done thinking.\n\n');
358
+ thinkingDone = true;
359
+ }
350
360
  process.stdout.write(event.text);
351
361
  break;
352
362
  case 'tool_start':
353
- stopSpinner(''); // Stop thinking spinner silently
363
+ if (isThinking && !thinkingDone) {
364
+ stopSpinner('');
365
+ process.stdout.write('\n...done thinking.\n\n');
366
+ thinkingDone = true;
367
+ }
354
368
  process.stdout.write(`[${event.name}] `);
355
369
  startSpinner();
356
370
  break;
@@ -410,18 +424,55 @@ async function runRepl(options) {
410
424
  if (options.session) {
411
425
  console.log(`Resuming session: ${session.id}`);
412
426
  }
413
- console.log('Type /quit to exit, /clear to reset conversation\n');
427
+ console.log('Type /? for help\n');
428
+
429
+ const showHelp = () => {
430
+ console.log('Available Commands:');
431
+ console.log(' /show Show model information');
432
+ console.log(' /clear Clear session context');
433
+ console.log(' /bye Exit');
434
+ console.log(' /?, /help Help for a command');
435
+ console.log('');
436
+ console.log('Use """ to begin a multi-line message.\n');
437
+ };
414
438
 
415
- const prompt = () => {
416
- rl.question('> ', async (input) => {
439
+ const showModel = () => {
440
+ console.log(` Model: ${options.model}`);
441
+ console.log(` Provider: ${options.provider}`);
442
+ console.log(` Session: ${session.id}\n`);
443
+ };
444
+
445
+ const promptUser = () => {
446
+ rl.question('>>> ', async (input) => {
417
447
  const trimmed = input.trim();
418
448
 
419
449
  if (!trimmed) {
420
- prompt();
450
+ promptUser();
451
+ return;
452
+ }
453
+
454
+ // Multi-line input mode
455
+ if (trimmed === '"""') {
456
+ let multiLine = '';
457
+ const collectLines = () => {
458
+ rl.question('... ', (line) => {
459
+ if (line.trim() === '"""') {
460
+ if (multiLine.trim()) {
461
+ handleMessage(multiLine.trim());
462
+ } else {
463
+ promptUser();
464
+ }
465
+ } else {
466
+ multiLine += (multiLine ? '\n' : '') + line;
467
+ collectLines();
468
+ }
469
+ });
470
+ };
471
+ collectLines();
421
472
  return;
422
473
  }
423
474
 
424
- if (trimmed === '/quit' || trimmed === '/exit') {
475
+ if (trimmed === '/bye' || trimmed === '/quit' || trimmed === '/exit') {
425
476
  console.log('Goodbye!');
426
477
  rl.close();
427
478
  process.exit(0);
@@ -430,64 +481,94 @@ async function runRepl(options) {
430
481
  if (trimmed === '/clear') {
431
482
  messages.length = 0;
432
483
  console.log('Conversation cleared.\n');
433
- prompt();
484
+ promptUser();
434
485
  return;
435
486
  }
436
487
 
437
- messages.push({ role: 'user', content: trimmed });
488
+ if (trimmed === '/?' || trimmed === '/help') {
489
+ showHelp();
490
+ promptUser();
491
+ return;
492
+ }
438
493
 
439
- process.stdout.write('\n[thinking] ');
440
- startSpinner();
441
- let assistantContent = '';
494
+ if (trimmed === '/show') {
495
+ showModel();
496
+ promptUser();
497
+ return;
498
+ }
442
499
 
443
- try {
444
- for await (const event of agentLoop({
445
- model: options.model,
446
- messages: [...messages],
447
- tools: coreTools,
448
- provider,
449
- context,
450
- })) {
451
- switch (event.type) {
452
- case 'thinking':
453
- // Already showing spinner, ignore thinking events
454
- break;
455
- case 'text_delta':
456
- stopSpinner(''); // Stop thinking spinner silently
500
+ await handleMessage(trimmed);
501
+ });
502
+ };
503
+
504
+ const handleMessage = async (text) => {
505
+ messages.push({ role: 'user', content: text });
506
+
507
+ let isThinking = false;
508
+ let thinkingDone = false;
509
+ let assistantContent = '';
510
+
511
+ try {
512
+ for await (const event of agentLoop({
513
+ model: options.model,
514
+ messages: [...messages],
515
+ tools: coreTools,
516
+ provider,
517
+ context,
518
+ })) {
519
+ switch (event.type) {
520
+ case 'thinking':
521
+ if (!isThinking) {
522
+ process.stdout.write('Thinking...\n');
523
+ isThinking = true;
524
+ }
525
+ if (event.text) {
457
526
  process.stdout.write(event.text);
458
- assistantContent += event.text;
459
- break;
460
- case 'tool_start':
461
- stopSpinner(''); // Stop thinking spinner silently
462
- process.stdout.write(`[${event.name}] `);
463
- startSpinner();
464
- break;
465
- case 'tool_result':
466
- stopSpinner('done');
467
- break;
468
- case 'tool_error':
469
- stopSpinner('error');
470
- break;
471
- case 'error':
472
- stopSpinner();
473
- console.error(`\nError: ${event.error}`);
474
- break;
475
- }
527
+ }
528
+ break;
529
+ case 'text_delta':
530
+ if (isThinking && !thinkingDone) {
531
+ stopSpinner('');
532
+ process.stdout.write('\n...done thinking.\n\n');
533
+ thinkingDone = true;
534
+ }
535
+ process.stdout.write(event.text);
536
+ assistantContent += event.text;
537
+ break;
538
+ case 'tool_start':
539
+ if (isThinking && !thinkingDone) {
540
+ stopSpinner('');
541
+ process.stdout.write('\n...done thinking.\n\n');
542
+ thinkingDone = true;
543
+ }
544
+ process.stdout.write(`[${event.name}] `);
545
+ startSpinner();
546
+ break;
547
+ case 'tool_result':
548
+ stopSpinner('done');
549
+ break;
550
+ case 'tool_error':
551
+ stopSpinner('error');
552
+ break;
553
+ case 'error':
554
+ stopSpinner();
555
+ console.error(`\nError: ${event.error}`);
556
+ break;
476
557
  }
558
+ }
477
559
 
478
- if (assistantContent) {
479
- messages.push({ role: 'assistant', content: assistantContent });
480
- }
481
- } catch (err) {
482
- console.error(`\nError: ${err.message}`);
560
+ if (assistantContent) {
561
+ messages.push({ role: 'assistant', content: assistantContent });
483
562
  }
563
+ } catch (err) {
564
+ console.error(`\nError: ${err.message}`);
565
+ }
484
566
 
485
- process.stdout.write('\n\n');
486
- prompt();
487
- });
567
+ process.stdout.write('\n\n');
568
+ promptUser();
488
569
  };
489
570
 
490
- prompt();
571
+ promptUser();
491
572
  }
492
573
 
493
574
  /**
package/dotbot.db CHANGED
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stevederico/dotbot",
3
- "version": "0.25.0",
3
+ "version": "0.26.0",
4
4
  "description": "AI agent CLI and library for Node.js — streaming, multi-provider, tool execution, autonomous tasks",
5
5
  "type": "module",
6
6
  "main": "index.js",