@bolloon/bolloon-agent 0.3.20 → 0.3.22

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.
@@ -353,11 +353,6 @@ export class PiAgentSession {
353
353
  this.skillRegistry.register(s);
354
354
  }
355
355
  console.log(`[loadSkills] 已加载 ${skills.length} 个 skill from ${resolved.join(', ')}`);
356
- if (skills.length > 0) {
357
- for (const s of skills) {
358
- console.log(` - ${s.name}: ${s.description.substring(0, 100)}${s.description.length > 100 ? '...' : ''}`);
359
- }
360
- }
361
356
  })
362
357
  .catch((err) => {
363
358
  console.error('[loadSkills] 加载失败:', err);
@@ -1442,15 +1437,6 @@ ${toolDefs}
1442
1437
  if (onStream) {
1443
1438
  onStream({ type: 'status', content: `✅ 处理完成,共 ${iteration - 1} 次循环`, tool: 'system' });
1444
1439
  }
1445
- const now = new Date().toISOString();
1446
- const identityPrefix = `${this.identity.name} | bolloon 智能体
1447
- <environment_details>
1448
- Current time: ${now}
1449
- Working directory: ${this.cwd}
1450
- Workspace root folder: ${this.cwd}
1451
- </environment_details>
1452
- `;
1453
- finalResponse = identityPrefix + finalResponse;
1454
1440
  this.messageHistory.push({ role: 'assistant', content: finalResponse });
1455
1441
  // React Harness: 循环结束
1456
1442
  try {
@@ -63,7 +63,7 @@ export const BOLLOON_BANNER = [
63
63
  `${C_DIM}Bolloon Agent v${BOLLOON_VERSION}${RESET}`,
64
64
  ].join('\n');
65
65
  /** 艺术字全部行 (图标在左, BOLLOON 艺术字在右), 供框内渲染 */
66
- function brandArtLines() {
66
+ export function brandArtLines() {
67
67
  const icon = BOLLOON_ICON.split('\n');
68
68
  const banner = BOLLOON_BANNER.split('\n');
69
69
  const gap = 2;
@@ -107,7 +107,7 @@ function stripAnsi(s) {
107
107
  return s.replace(/\x1b\[[0-9;]*m/g, '');
108
108
  }
109
109
  /** 显示宽度: CJK / 全角符号算 2, 其余算 1 (ANSI 转义不计入) */
110
- function dispWidth(s) {
110
+ export function dispWidth(s) {
111
111
  const clean = s.replace(/\x1b\[[0-9;]*m/g, '');
112
112
  let n = 0;
113
113
  for (const ch of clean) {
package/dist/index.js CHANGED
@@ -15,7 +15,7 @@ import { createSubAgentManager } from './agents/subagent-manager.js';
15
15
  import { getGlobalSharedContext } from './social/global-shared-context.js';
16
16
  import { createBollharnessIntegration } from './bollharness-integration/index.js';
17
17
  import * as readline from 'readline';
18
- import { printBanner, renderDialog, renderUserMessage, renderAgentMessage, renderToolCall, flowConnector, termWidth } from './cli/loading-tui.js';
18
+ import { printBanner, renderDialog, renderUserMessage, renderAgentMessage, renderToolCall, flowConnector, termWidth, brandArtLines, boxTop, boxRow, boxBottom, dispWidth } from './cli/loading-tui.js';
19
19
  // 启动自动检查更新:后台、节流、检测到新版本自动安装(可被 --no-update / BOLLOON_SKIP_UPDATE 关闭)
20
20
  import { createRequire } from 'module';
21
21
  const _require = createRequire(import.meta.url);
@@ -345,16 +345,8 @@ function rpcErr(code, msg) {
345
345
  }
346
346
  // ---------------------------------------------------------------------------
347
347
  // CLI with persistent bottom prompt
348
- // ---------------------------------------------------------------------------
349
- const SAVE_CURSOR = '\x1b[s';
350
- const RESTORE_CURSOR = '\x1b[u';
351
- const MOVE_TO_BOTTOM = '\x1b[999A';
352
- const HIDE_CURSOR_SEQ = '\x1b[?25l';
353
- const SHOW_CURSOR_SEQ = '\x1b[?25h';
354
- const MOVE_UP_1 = '\x1b[1A';
348
+ // 2026-07-28: 改用 readline.createInterface + replReadline 循环
355
349
  let isRunning = false;
356
- let currentInput = '';
357
- let promptVisible = false;
358
350
  let queueMode = false;
359
351
  const pendingQueue = [];
360
352
  // 底部状态栏数据
@@ -379,40 +371,22 @@ function statusBarLine() {
379
371
  const bar = C_OK + '█'.repeat(filled) + C_DIM + '░'.repeat(barLen - filled) + RESET;
380
372
  return `${C_ACCENT}${cliModelName}${RESET}${C_DIM} │${RESET} ${cliAgentName} ${C_DIM}│${RESET} ⏱ ${C_ACCENT}${dur}${RESET} ${C_DIM}│${RESET} ${bar} ${C_DIM}${cliContextPct}%${RESET}`;
381
373
  }
382
- function showBottomPrompt() {
383
- if (!isRunning)
384
- return;
385
- promptVisible = true;
386
- const tw = process.stdout.columns || 80;
387
- const sep = C_DIM + '─'.repeat(tw) + RESET;
388
- const hint = currentInput.length === 0 && !queueMode
389
- ? ` ${C_DIM}!cmd${RESET} ${C_DIM}/queue${RESET} ${C_DIM}/help${RESET}`
390
- : queueMode ? ` ${C_WARN}[队列${pendingQueue.length}]${RESET}` : '';
391
- const prefix = queueMode ? `${C_WARN}▸${RESET}` : `${C_ACCENT}❯${RESET}`;
392
- process.stdout.write(`\n${sep}\n${statusBarLine()}\n${sep}\n${C_DIM}${'─'.repeat(tw)}${RESET}\n${prefix} ${currentInput}${hint}`);
393
- }
394
- function clearPromptLine() {
395
- promptVisible = false;
396
- }
397
374
  function startCLI(comm) {
398
375
  isRunning = true;
399
- currentInput = '';
400
- promptVisible = false;
401
- try {
402
- process.stdin.setRawMode(true);
403
- }
404
- catch {
405
- }
406
- readline.emitKeypressEvents(process.stdin);
407
- process.stdout.write(CLEAR_LINE);
408
- // ── Bolloon Agent 仪表盘 (ASCII 艺术字 + 品牌图标) ──
409
- printBanner(_BOLLOON_VERSION);
376
+ // CLI 模式下过滤 [xxx] 内部日志
377
+ const _origLog = console.log;
378
+ const _origWarn = console.warn;
379
+ const _isInternal = (args) => args.length && typeof args[0] === 'string' && /^\[[A-Za-z _\-.]+/.test(args[0]);
380
+ console.log = (...args) => { if (_isInternal(args))
381
+ return; _origLog.apply(console, args); };
382
+ console.warn = (...args) => { if (_isInternal(args))
383
+ return; _origWarn.apply(console, args); };
410
384
  let peerCount = 0;
411
385
  try {
412
386
  peerCount = comm.getConnections().length;
413
387
  }
414
388
  catch { /* */ }
415
- // 读取 LLM 模型名 (支持多 provider)
389
+ // 读取 LLM 模型名
416
390
  const providerNames = [
417
391
  ['OPENAI_API_KEY', 'OpenAI'],
418
392
  ['ANTHROPIC_API_KEY', 'Anthropic'],
@@ -427,64 +401,39 @@ function startCLI(comm) {
427
401
  cliModelName = foundProvider ? foundProvider[1] : '未配置';
428
402
  cliAgentName = agentIdentity?.name || 'bolloon';
429
403
  cliStartTime = Date.now();
430
- process.stdout.write(`${C_DIM}Bolloon CLI ready. 输入 !cmd /queue /help${RESET}\n\n`);
431
- showBottomPrompt();
432
- const handleInput = (chunk, key) => {
404
+ process.stdout.write(`${C_DIM}输入 !cmd 执行终端 · /queue 入队 · /help 帮助${RESET}\n\n`);
405
+ // 启动框: logo 左对齐(无状态栏 — 状态栏在输入框上方)
406
+ const art = brandArtLines();
407
+ const maxArt = art.reduce((m, l) => Math.max(m, dispWidth(l)), 0);
408
+ const boxW = Math.min(termWidth() - 2, Math.max(40, maxArt) + 4);
409
+ process.stdout.write(boxTop('Bolloon Agent', boxW) + '\n');
410
+ for (const l of art)
411
+ process.stdout.write(boxRow(l, boxW, 'left') + '\n');
412
+ process.stdout.write(boxBottom(boxW) + '\n\n');
413
+ // readline 输入循环(底部没有独立状态栏)
414
+ replReadline(comm);
415
+ }
416
+ async function replReadline(comm) {
417
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
418
+ const SEP = '\x1b[90m─';
419
+ const RST = '\x1b[0m';
420
+ while (isRunning) {
421
+ const tw = process.stdout.columns || 80;
422
+ const sepLine = SEP.repeat(tw) + RST;
423
+ const prefix = queueMode ? `${C_WARN}▸${RST}` : `${C_ACCENT}❯${RST}`;
424
+ const raw = await new Promise(resolve => rl.question(`\n${sepLine}\n${statusBarLine()}\n${sepLine}\n${prefix} `, resolve));
425
+ const trimmed = raw.trim();
426
+ process.stdout.write(`\n${sepLine}\n\n\n\n\n`);
427
+ if (!trimmed)
428
+ continue;
433
429
  if (!isRunning)
434
- return;
435
- if (!key)
436
- return;
437
- if (key.ctrl && key.name === 'c') {
438
- clearPromptLine();
439
- process.stdout.write(`\n${CYAN}👋 再见!${RESET}\n`);
440
- try {
441
- process.stdin.setRawMode(false);
442
- }
443
- catch { }
444
- process.exit(0);
445
- return;
446
- }
447
- if (key.name === 'return') {
448
- const trimmed = currentInput.trim();
449
- currentInput = '';
450
- clearPromptLine();
451
- if (trimmed) {
452
- process.stdout.write('\n');
453
- processInput(trimmed, comm).then(() => {
454
- if (isRunning)
455
- showBottomPrompt();
456
- });
457
- }
458
- else {
459
- showBottomPrompt();
460
- }
461
- return;
462
- }
463
- if (key.name === 'backspace') {
464
- if (currentInput.length > 0) {
465
- currentInput = currentInput.slice(0, -1);
466
- showBottomPrompt();
467
- }
468
- return;
469
- }
470
- if (key.name === 'escape' || (key.ctrl && key.name === 'u')) {
471
- currentInput = '';
472
- showBottomPrompt();
473
- return;
474
- }
475
- if (key.name === 'tab') {
476
- return;
477
- }
478
- if (key.name && key.name.length === 1) {
479
- currentInput += chunk.toString();
480
- showBottomPrompt();
481
- }
482
- };
483
- process.stdin.on('data', handleInput);
484
- process.on('exit', () => {
485
- isRunning = false;
486
- process.stdout.write(SHOW_CURSOR_SEQ);
487
- });
430
+ break;
431
+ await processInput(trimmed, comm);
432
+ }
433
+ rl.close();
434
+ process.stdout.write(`\n${CYAN}👋 再见!${RESET}\n`);
435
+ process.stdin.destroy();
436
+ comm.stop();
488
437
  }
489
438
  async function processInput(input, comm) {
490
439
  const trimmed = input.trim();
@@ -546,11 +495,8 @@ async function processInput(input, comm) {
546
495
  return;
547
496
  }
548
497
  if (trimmed === '退出' || trimmed === 'exit' || trimmed === 'quit') {
549
- clearPromptLine();
550
- process.stdout.write(`${CYAN}👋 再见!${RESET}\n`);
498
+ process.stdout.write(`\n${CYAN}👋 再见!${RESET}\n`);
551
499
  isRunning = false;
552
- process.stdin.destroy();
553
- comm.stop();
554
500
  return;
555
501
  }
556
502
  if (trimmed.toLowerCase() === 'peers') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bolloon/bolloon-agent",
3
- "version": "0.3.20",
3
+ "version": "0.3.22",
4
4
  "type": "module",
5
5
  "description": "P2P AI Document Agent - 全局安装后执行 `bolloon` 启动产品",
6
6
  "main": "dist/cli-entry.js",