@bgicli/bgicli 2.2.15 → 2.3.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/dist/bgi.js +161 -29
- package/package.json +1 -1
package/dist/bgi.js
CHANGED
|
@@ -14218,7 +14218,7 @@ ${shortSummary}`);
|
|
|
14218
14218
|
}
|
|
14219
14219
|
|
|
14220
14220
|
// src/chat.ts
|
|
14221
|
-
async function chat(messages, config, systemPrompt2) {
|
|
14221
|
+
async function chat(messages, config, systemPrompt2, stats, signal) {
|
|
14222
14222
|
const prov = PROVIDERS[config.provider];
|
|
14223
14223
|
if (!prov) throw new Error(`Unknown provider: ${config.provider}`);
|
|
14224
14224
|
if (config.provider === "custom") {
|
|
@@ -14235,13 +14235,28 @@ async function chat(messages, config, systemPrompt2) {
|
|
|
14235
14235
|
{ role: "system", content: systemPrompt2 },
|
|
14236
14236
|
...messages
|
|
14237
14237
|
];
|
|
14238
|
-
return await streamLoop(client, fullMessages, config.model);
|
|
14238
|
+
return await streamLoop(client, fullMessages, config.model, stats, signal);
|
|
14239
14239
|
}
|
|
14240
|
-
async function streamLoop(client, messages, model) {
|
|
14240
|
+
async function streamLoop(client, messages, model, stats, signal) {
|
|
14241
14241
|
let finalText = "";
|
|
14242
14242
|
for (let round = 0; round < 20; round++) {
|
|
14243
|
+
if (signal?.aborted) break;
|
|
14243
14244
|
messages = deduplicateSkillInjections(trimToolOutputs(messages));
|
|
14244
|
-
|
|
14245
|
+
let streamResult;
|
|
14246
|
+
try {
|
|
14247
|
+
streamResult = await streamOnce(client, messages, model, signal);
|
|
14248
|
+
} catch (err) {
|
|
14249
|
+
if (signal?.aborted || err instanceof Error && (err.name === "AbortError" || err.message.includes("abort"))) {
|
|
14250
|
+
process.stdout.write(source_default.yellow("\n [\u4EFB\u52A1\u5DF2\u4E2D\u65AD]\n"));
|
|
14251
|
+
break;
|
|
14252
|
+
}
|
|
14253
|
+
throw err;
|
|
14254
|
+
}
|
|
14255
|
+
const { text, toolCalls, finishReason, inputTokens, outputTokens } = streamResult;
|
|
14256
|
+
if (stats) {
|
|
14257
|
+
stats.inputTokens += inputTokens;
|
|
14258
|
+
stats.outputTokens += outputTokens;
|
|
14259
|
+
}
|
|
14245
14260
|
if (text) finalText = text;
|
|
14246
14261
|
if (finishReason === "tool_calls" && toolCalls.length > 0) {
|
|
14247
14262
|
messages.push({
|
|
@@ -14261,15 +14276,32 @@ async function streamLoop(client, messages, model) {
|
|
|
14261
14276
|
const label = source_default.dim(`[\u5DE5\u5177: ${tc.name}(${summarizeArgs(args)})]`);
|
|
14262
14277
|
const t0 = Date.now();
|
|
14263
14278
|
process.stdout.write(`
|
|
14264
|
-
${label}
|
|
14265
|
-
`);
|
|
14279
|
+
${label} `);
|
|
14266
14280
|
let streamedLines = 0;
|
|
14267
14281
|
let lastLineWasEmpty = false;
|
|
14282
|
+
let spinnerCleared = false;
|
|
14268
14283
|
const MAX_STREAM_LINES = 200;
|
|
14269
|
-
let spin = null;
|
|
14270
14284
|
let frame = 0;
|
|
14285
|
+
const spin = setInterval(() => {
|
|
14286
|
+
if (spinnerCleared) return;
|
|
14287
|
+
const secs = ((Date.now() - t0) / 1e3).toFixed(1);
|
|
14288
|
+
process.stdout.write(
|
|
14289
|
+
`\r${label} ${source_default.cyan(SPIN_FRAMES[frame++ % SPIN_FRAMES.length])} ${source_default.dim(secs + "s")}`
|
|
14290
|
+
);
|
|
14291
|
+
}, 80);
|
|
14292
|
+
const clearSpinner = () => {
|
|
14293
|
+
if (spinnerCleared) return;
|
|
14294
|
+
spinnerCleared = true;
|
|
14295
|
+
clearInterval(spin);
|
|
14296
|
+
process.stdout.write("\r\x1B[2K");
|
|
14297
|
+
};
|
|
14271
14298
|
const onStream = isBash ? (chunk) => {
|
|
14272
14299
|
if (streamedLines >= MAX_STREAM_LINES) return;
|
|
14300
|
+
if (streamedLines === 0) {
|
|
14301
|
+
clearSpinner();
|
|
14302
|
+
process.stdout.write(`${label}
|
|
14303
|
+
`);
|
|
14304
|
+
}
|
|
14273
14305
|
const lines = chunk.split("\n");
|
|
14274
14306
|
for (let i2 = 0; i2 < lines.length; i2++) {
|
|
14275
14307
|
const line = lines[i2];
|
|
@@ -14289,19 +14321,12 @@ ${label}
|
|
|
14289
14321
|
}
|
|
14290
14322
|
}
|
|
14291
14323
|
} : void 0;
|
|
14292
|
-
if (!isBash) {
|
|
14293
|
-
spin = setInterval(() => {
|
|
14294
|
-
const secs = ((Date.now() - t0) / 1e3).toFixed(1);
|
|
14295
|
-
process.stdout.write(
|
|
14296
|
-
`\r ${source_default.cyan(SPIN_FRAMES[frame++ % SPIN_FRAMES.length])} ${source_default.dim(secs + "s")}`
|
|
14297
|
-
);
|
|
14298
|
-
}, 80);
|
|
14299
|
-
}
|
|
14300
14324
|
const result = await executeTool(tc.name, args, onStream);
|
|
14301
|
-
if (
|
|
14302
|
-
|
|
14303
|
-
|
|
14325
|
+
if (stats) {
|
|
14326
|
+
if (result.error) stats.failCmds++;
|
|
14327
|
+
else stats.successCmds++;
|
|
14304
14328
|
}
|
|
14329
|
+
clearSpinner();
|
|
14305
14330
|
const elapsed = ((Date.now() - t0) / 1e3).toFixed(1);
|
|
14306
14331
|
const doneIcon = result.error ? source_default.yellow("\u2717") : source_default.green("\u2713");
|
|
14307
14332
|
if (isBash && streamedLines > 0) {
|
|
@@ -14333,18 +14358,25 @@ OUTPUT: ${result.output}` : result.output
|
|
|
14333
14358
|
}
|
|
14334
14359
|
return finalText;
|
|
14335
14360
|
}
|
|
14336
|
-
async function streamOnce(client, messages, model) {
|
|
14361
|
+
async function streamOnce(client, messages, model, signal) {
|
|
14337
14362
|
const stream = await client.chat.completions.create({
|
|
14338
14363
|
model,
|
|
14339
14364
|
messages,
|
|
14340
14365
|
tools: TOOL_DEFINITIONS,
|
|
14341
|
-
stream: true
|
|
14342
|
-
|
|
14366
|
+
stream: true,
|
|
14367
|
+
stream_options: { include_usage: true }
|
|
14368
|
+
}, { signal });
|
|
14343
14369
|
let text = "";
|
|
14344
14370
|
const toolCallMap = {};
|
|
14345
14371
|
let finishReason = null;
|
|
14372
|
+
let inputTokens = 0;
|
|
14373
|
+
let outputTokens = 0;
|
|
14346
14374
|
process.stdout.write(source_default.green("BGI \u203A "));
|
|
14347
14375
|
for await (const chunk of stream) {
|
|
14376
|
+
if (chunk.usage) {
|
|
14377
|
+
inputTokens = chunk.usage.prompt_tokens ?? 0;
|
|
14378
|
+
outputTokens = chunk.usage.completion_tokens ?? 0;
|
|
14379
|
+
}
|
|
14348
14380
|
const choice = chunk.choices[0];
|
|
14349
14381
|
if (!choice) continue;
|
|
14350
14382
|
const delta = choice.delta;
|
|
@@ -14375,7 +14407,9 @@ async function streamOnce(client, messages, model) {
|
|
|
14375
14407
|
return {
|
|
14376
14408
|
text,
|
|
14377
14409
|
toolCalls: Object.values(toolCallMap),
|
|
14378
|
-
finishReason
|
|
14410
|
+
finishReason,
|
|
14411
|
+
inputTokens,
|
|
14412
|
+
outputTokens
|
|
14379
14413
|
};
|
|
14380
14414
|
}
|
|
14381
14415
|
function estimateTokens(messages) {
|
|
@@ -15876,7 +15910,7 @@ function clearCheckpoints(sessionId) {
|
|
|
15876
15910
|
|
|
15877
15911
|
// src/index.ts
|
|
15878
15912
|
var import_fs7 = require("fs");
|
|
15879
|
-
var VERSION2 = "2.
|
|
15913
|
+
var VERSION2 = "2.3.0";
|
|
15880
15914
|
var SKILLHUB_HUBS = {
|
|
15881
15915
|
bgi: { label: "BGI\u5185\u7F51", apiBase: "https://clawhub.ai", backend: "clawhub" },
|
|
15882
15916
|
clawhub: { label: "clawhub.ai", apiBase: "https://clawhub.ai", backend: "clawhub" },
|
|
@@ -17520,10 +17554,8 @@ async function main() {
|
|
|
17520
17554
|
historySize: 100
|
|
17521
17555
|
});
|
|
17522
17556
|
rl.on("close", () => {
|
|
17523
|
-
console.log(source_default.dim("\n\u518D\u89C1\uFF01"));
|
|
17524
17557
|
process.exit(0);
|
|
17525
17558
|
});
|
|
17526
|
-
process.on("SIGINT", () => rl.close());
|
|
17527
17559
|
await firstRunIfNeeded(rl);
|
|
17528
17560
|
const cfg = loadConfig();
|
|
17529
17561
|
const prov = PROVIDERS[cfg.provider];
|
|
@@ -17548,6 +17580,20 @@ async function main() {
|
|
|
17548
17580
|
console.log(source_default.dim(" \u8F93\u5165\u95EE\u9898\u5F00\u59CB\u5BF9\u8BDD /help \u67E5\u770B\u547D\u4EE4 /cat \u6280\u80FD\u5206\u7C7B @\u6587\u4EF6\u8DEF\u5F84 \u5185\u5D4C\u6587\u4EF6"));
|
|
17549
17581
|
console.log();
|
|
17550
17582
|
let dbRegistry2 = loadDbRegistry();
|
|
17583
|
+
if (Object.keys(dbRegistry2.databases).length === 0) {
|
|
17584
|
+
process.stdout.write(source_default.dim(" \u6B63\u5728\u81EA\u52A8\u626B\u63CF\u53C2\u8003\u6570\u636E\u5E93...\n"));
|
|
17585
|
+
const report = scanForDatabases([]);
|
|
17586
|
+
if (report.found.length > 0) {
|
|
17587
|
+
for (const entry of report.found) dbRegistry2.databases[entry.id] = entry;
|
|
17588
|
+
dbRegistry2.lastScan = (/* @__PURE__ */ new Date()).toISOString();
|
|
17589
|
+
saveDbRegistry(dbRegistry2);
|
|
17590
|
+
process.stdout.write(source_default.green(` \u2713 \u53D1\u73B0 ${report.found.length} \u4E2A\u6570\u636E\u5E93\uFF0C\u5DF2\u81EA\u52A8\u6CE8\u518C (/db list \u67E5\u770B)
|
|
17591
|
+
`));
|
|
17592
|
+
} else {
|
|
17593
|
+
process.stdout.write(source_default.dim(" \u672A\u53D1\u73B0\u5DF2\u77E5\u6570\u636E\u5E93\uFF08\u53EF\u7528 /db add <\u8DEF\u5F84> \u624B\u52A8\u6DFB\u52A0\uFF09\n"));
|
|
17594
|
+
}
|
|
17595
|
+
console.log();
|
|
17596
|
+
}
|
|
17551
17597
|
let systemPrompt2 = buildSystemPrompt(buildDbPromptSection(dbRegistry2));
|
|
17552
17598
|
let history = [];
|
|
17553
17599
|
let thinkMode = false;
|
|
@@ -17567,6 +17613,79 @@ async function main() {
|
|
|
17567
17613
|
}
|
|
17568
17614
|
let lastCheckpointMsgCount = 0;
|
|
17569
17615
|
const CHECKPOINT_INTERVAL = 6;
|
|
17616
|
+
const sessionStartTime = Date.now();
|
|
17617
|
+
const sessionStats = { inputTokens: 0, outputTokens: 0, successCmds: 0, failCmds: 0 };
|
|
17618
|
+
let lastSigintTime = 0;
|
|
17619
|
+
let currentAbortController = null;
|
|
17620
|
+
let exiting = false;
|
|
17621
|
+
function formatDuration(ms) {
|
|
17622
|
+
const s2 = Math.floor(ms / 1e3);
|
|
17623
|
+
const h2 = Math.floor(s2 / 3600);
|
|
17624
|
+
const m2 = Math.floor(s2 % 3600 / 60);
|
|
17625
|
+
const sec = s2 % 60;
|
|
17626
|
+
if (h2 > 0) return `${h2}h ${m2}m ${sec}s`;
|
|
17627
|
+
if (m2 > 0) return `${m2}m ${sec}s`;
|
|
17628
|
+
return `${sec}s`;
|
|
17629
|
+
}
|
|
17630
|
+
function saveSessionMemory() {
|
|
17631
|
+
const memDir = (0, import_path6.join)(BGI_DIR, "memory");
|
|
17632
|
+
if (!(0, import_fs6.existsSync)(memDir)) (0, import_fs6.mkdirSync)(memDir, { recursive: true });
|
|
17633
|
+
const dateStr = new Date(sessionStartTime).toISOString().slice(0, 10);
|
|
17634
|
+
const filename = (0, import_path6.join)(memDir, `${dateStr}-${sessionId}.md`);
|
|
17635
|
+
const lines = [
|
|
17636
|
+
`# \u4F1A\u8BDD\u8BB0\u5FC6 ${new Date(sessionStartTime).toLocaleString("zh-CN")}`,
|
|
17637
|
+
``,
|
|
17638
|
+
`- \u6A21\u578B: ${loadConfig().model}`,
|
|
17639
|
+
`- Token: \u8F93\u5165 ${sessionStats.inputTokens} / \u8F93\u51FA ${sessionStats.outputTokens}`,
|
|
17640
|
+
`- \u547D\u4EE4: ${sessionStats.successCmds} \u6210\u529F / ${sessionStats.failCmds} \u5931\u8D25`,
|
|
17641
|
+
``
|
|
17642
|
+
];
|
|
17643
|
+
let turnCount = 0;
|
|
17644
|
+
for (let i2 = 0; i2 < history.length; i2++) {
|
|
17645
|
+
const msg = history[i2];
|
|
17646
|
+
if (msg.role === "user" && typeof msg.content === "string") {
|
|
17647
|
+
turnCount++;
|
|
17648
|
+
const content = msg.content.slice(0, 500) + (msg.content.length > 500 ? "..." : "");
|
|
17649
|
+
lines.push(`## \u5BF9\u8BDD ${turnCount}`);
|
|
17650
|
+
lines.push(`**\u7528\u6237**: ${content}`);
|
|
17651
|
+
} else if (msg.role === "assistant" && typeof msg.content === "string") {
|
|
17652
|
+
const content = msg.content.slice(0, 500) + (msg.content.length > 500 ? "..." : "");
|
|
17653
|
+
lines.push(`**BGI**: ${content}`);
|
|
17654
|
+
lines.push(``);
|
|
17655
|
+
}
|
|
17656
|
+
}
|
|
17657
|
+
(0, import_fs6.writeFileSync)(filename, lines.join("\n"), "utf8");
|
|
17658
|
+
console.log(source_default.green(` \u2713 \u8BB0\u5FC6\u5DF2\u4FDD\u5B58: ${filename}`));
|
|
17659
|
+
}
|
|
17660
|
+
async function exitWithReport() {
|
|
17661
|
+
if (exiting) return;
|
|
17662
|
+
exiting = true;
|
|
17663
|
+
const runtime = formatDuration(Date.now() - sessionStartTime);
|
|
17664
|
+
console.log("\n" + source_default.bold.cyan("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 \u4F1A\u8BDD\u62A5\u544A \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"));
|
|
17665
|
+
console.log(` \u8FD0\u884C\u65F6\u95F4: ${source_default.white(runtime)}`);
|
|
17666
|
+
console.log(` \u6D88\u8017 Token: ${source_default.yellow("\u8F93\u5165")} ${source_default.bold(String(sessionStats.inputTokens))} | ${source_default.green("\u8F93\u51FA")} ${source_default.bold(String(sessionStats.outputTokens))}`);
|
|
17667
|
+
console.log(` \u6267\u884C\u547D\u4EE4: ${source_default.green("\u2713 " + sessionStats.successCmds + " \u6210\u529F")} ${sessionStats.failCmds > 0 ? source_default.yellow("\u2717 " + sessionStats.failCmds + " \u5931\u8D25") : source_default.dim("\u2717 0 \u5931\u8D25")}`);
|
|
17668
|
+
console.log(source_default.bold.cyan("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"));
|
|
17669
|
+
try {
|
|
17670
|
+
const ans = await question(rl, source_default.cyan("\n \u662F\u5426\u4FDD\u5B58\u672C\u6B21\u4F1A\u8BDD\u8BB0\u5FC6\uFF1F[y/N] "));
|
|
17671
|
+
if (ans.trim().toLowerCase() === "y") saveSessionMemory();
|
|
17672
|
+
} catch {
|
|
17673
|
+
}
|
|
17674
|
+
console.log(source_default.dim("\n\u518D\u89C1\uFF01"));
|
|
17675
|
+
process.exit(0);
|
|
17676
|
+
}
|
|
17677
|
+
process.on("SIGINT", () => {
|
|
17678
|
+
const now = Date.now();
|
|
17679
|
+
if (now - lastSigintTime < 2e3) {
|
|
17680
|
+
exitWithReport().catch(() => process.exit(0));
|
|
17681
|
+
} else {
|
|
17682
|
+
lastSigintTime = now;
|
|
17683
|
+
if (currentAbortController) {
|
|
17684
|
+
currentAbortController.abort();
|
|
17685
|
+
}
|
|
17686
|
+
process.stdout.write(source_default.yellow("\n\n [\u4EFB\u52A1\u5DF2\u4E2D\u65AD] \u518D\u6309\u4E00\u6B21 Ctrl+C \u9000\u51FA\n\n"));
|
|
17687
|
+
}
|
|
17688
|
+
});
|
|
17570
17689
|
while (true) {
|
|
17571
17690
|
let input;
|
|
17572
17691
|
const thinkIndicator = thinkMode ? source_default.yellow("[\u601D\u8003]") + " " : "";
|
|
@@ -17578,9 +17697,8 @@ async function main() {
|
|
|
17578
17697
|
const trimmed = input.trim();
|
|
17579
17698
|
if (!trimmed) continue;
|
|
17580
17699
|
if (["exit", "quit", "q", "/exit", "/quit"].includes(trimmed.toLowerCase())) {
|
|
17581
|
-
|
|
17582
|
-
|
|
17583
|
-
break;
|
|
17700
|
+
await exitWithReport();
|
|
17701
|
+
return;
|
|
17584
17702
|
}
|
|
17585
17703
|
if (trimmed.startsWith("/")) {
|
|
17586
17704
|
const result = await handleCommand(trimmed, rl, history, thinkMode, injectedSkills);
|
|
@@ -17636,7 +17754,14 @@ ${expanded}` : expanded;
|
|
|
17636
17754
|
history.push({ role: "user", content: userContent });
|
|
17637
17755
|
try {
|
|
17638
17756
|
const currentCfg = loadConfig();
|
|
17639
|
-
|
|
17757
|
+
currentAbortController = new AbortController();
|
|
17758
|
+
const reply = await chat(history, currentCfg, systemPrompt2, sessionStats, currentAbortController.signal);
|
|
17759
|
+
currentAbortController = null;
|
|
17760
|
+
if (!reply && history[history.length - 1]?.role === "user") {
|
|
17761
|
+
history.pop();
|
|
17762
|
+
console.log();
|
|
17763
|
+
continue;
|
|
17764
|
+
}
|
|
17640
17765
|
history.push({ role: "assistant", content: reply });
|
|
17641
17766
|
history = await maybeCompact(history, currentCfg);
|
|
17642
17767
|
autoSaveSession();
|
|
@@ -17651,7 +17776,13 @@ ${expanded}` : expanded;
|
|
|
17651
17776
|
[\u6FC0\u6D3B Skill: ${ids}]`));
|
|
17652
17777
|
}
|
|
17653
17778
|
} catch (err) {
|
|
17779
|
+
currentAbortController = null;
|
|
17654
17780
|
const msg = err instanceof Error ? err.message : String(err);
|
|
17781
|
+
if (err instanceof Error && (err.name === "AbortError" || msg.toLowerCase().includes("abort"))) {
|
|
17782
|
+
history.pop();
|
|
17783
|
+
console.log();
|
|
17784
|
+
continue;
|
|
17785
|
+
}
|
|
17655
17786
|
console.error(source_default.red(`
|
|
17656
17787
|
\u9519\u8BEF: ${msg}
|
|
17657
17788
|
`));
|
|
@@ -17659,6 +17790,7 @@ ${expanded}` : expanded;
|
|
|
17659
17790
|
}
|
|
17660
17791
|
console.log();
|
|
17661
17792
|
}
|
|
17793
|
+
await exitWithReport();
|
|
17662
17794
|
}
|
|
17663
17795
|
function question(rl, prompt) {
|
|
17664
17796
|
return new Promise((resolve4, reject) => {
|