@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.
- package/dist/agents/pi-sdk.js +0 -14
- package/dist/cli/loading-tui.js +2 -2
- package/dist/index.js +44 -98
- package/package.json +1 -1
package/dist/agents/pi-sdk.js
CHANGED
|
@@ -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 {
|
package/dist/cli/loading-tui.js
CHANGED
|
@@ -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
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
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 模型名
|
|
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}
|
|
431
|
-
|
|
432
|
-
const
|
|
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
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
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
|
-
|
|
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') {
|