@bgicli/bgicli 2.2.16 → 2.3.1
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 +139 -16
- 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({
|
|
@@ -14307,6 +14322,10 @@ ${label} `);
|
|
|
14307
14322
|
}
|
|
14308
14323
|
} : void 0;
|
|
14309
14324
|
const result = await executeTool(tc.name, args, onStream);
|
|
14325
|
+
if (stats) {
|
|
14326
|
+
if (result.error) stats.failCmds++;
|
|
14327
|
+
else stats.successCmds++;
|
|
14328
|
+
}
|
|
14310
14329
|
clearSpinner();
|
|
14311
14330
|
const elapsed = ((Date.now() - t0) / 1e3).toFixed(1);
|
|
14312
14331
|
const doneIcon = result.error ? source_default.yellow("\u2717") : source_default.green("\u2713");
|
|
@@ -14339,18 +14358,25 @@ OUTPUT: ${result.output}` : result.output
|
|
|
14339
14358
|
}
|
|
14340
14359
|
return finalText;
|
|
14341
14360
|
}
|
|
14342
|
-
async function streamOnce(client, messages, model) {
|
|
14361
|
+
async function streamOnce(client, messages, model, signal) {
|
|
14343
14362
|
const stream = await client.chat.completions.create({
|
|
14344
14363
|
model,
|
|
14345
14364
|
messages,
|
|
14346
14365
|
tools: TOOL_DEFINITIONS,
|
|
14347
|
-
stream: true
|
|
14348
|
-
|
|
14366
|
+
stream: true,
|
|
14367
|
+
stream_options: { include_usage: true }
|
|
14368
|
+
}, { signal });
|
|
14349
14369
|
let text = "";
|
|
14350
14370
|
const toolCallMap = {};
|
|
14351
14371
|
let finishReason = null;
|
|
14372
|
+
let inputTokens = 0;
|
|
14373
|
+
let outputTokens = 0;
|
|
14352
14374
|
process.stdout.write(source_default.green("BGI \u203A "));
|
|
14353
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
|
+
}
|
|
14354
14380
|
const choice = chunk.choices[0];
|
|
14355
14381
|
if (!choice) continue;
|
|
14356
14382
|
const delta = choice.delta;
|
|
@@ -14381,7 +14407,9 @@ async function streamOnce(client, messages, model) {
|
|
|
14381
14407
|
return {
|
|
14382
14408
|
text,
|
|
14383
14409
|
toolCalls: Object.values(toolCallMap),
|
|
14384
|
-
finishReason
|
|
14410
|
+
finishReason,
|
|
14411
|
+
inputTokens,
|
|
14412
|
+
outputTokens
|
|
14385
14413
|
};
|
|
14386
14414
|
}
|
|
14387
14415
|
function estimateTokens(messages) {
|
|
@@ -15882,7 +15910,7 @@ function clearCheckpoints(sessionId) {
|
|
|
15882
15910
|
|
|
15883
15911
|
// src/index.ts
|
|
15884
15912
|
var import_fs7 = require("fs");
|
|
15885
|
-
var VERSION2 = "2.
|
|
15913
|
+
var VERSION2 = "2.3.1";
|
|
15886
15914
|
var SKILLHUB_HUBS = {
|
|
15887
15915
|
bgi: { label: "BGI\u5185\u7F51", apiBase: "https://clawhub.ai", backend: "clawhub" },
|
|
15888
15916
|
clawhub: { label: "clawhub.ai", apiBase: "https://clawhub.ai", backend: "clawhub" },
|
|
@@ -17525,11 +17553,10 @@ async function main() {
|
|
|
17525
17553
|
terminal: true,
|
|
17526
17554
|
historySize: 100
|
|
17527
17555
|
});
|
|
17556
|
+
let sigintHandling = false;
|
|
17528
17557
|
rl.on("close", () => {
|
|
17529
|
-
|
|
17530
|
-
process.exit(0);
|
|
17558
|
+
if (!sigintHandling) process.exit(0);
|
|
17531
17559
|
});
|
|
17532
|
-
process.on("SIGINT", () => rl.close());
|
|
17533
17560
|
await firstRunIfNeeded(rl);
|
|
17534
17561
|
const cfg = loadConfig();
|
|
17535
17562
|
const prov = PROVIDERS[cfg.provider];
|
|
@@ -17587,6 +17614,89 @@ async function main() {
|
|
|
17587
17614
|
}
|
|
17588
17615
|
let lastCheckpointMsgCount = 0;
|
|
17589
17616
|
const CHECKPOINT_INTERVAL = 6;
|
|
17617
|
+
const sessionStartTime = Date.now();
|
|
17618
|
+
const sessionStats = { inputTokens: 0, outputTokens: 0, successCmds: 0, failCmds: 0 };
|
|
17619
|
+
let lastSigintTime = 0;
|
|
17620
|
+
let currentAbortController = null;
|
|
17621
|
+
let exiting = false;
|
|
17622
|
+
function formatDuration(ms) {
|
|
17623
|
+
const s2 = Math.floor(ms / 1e3);
|
|
17624
|
+
const h2 = Math.floor(s2 / 3600);
|
|
17625
|
+
const m2 = Math.floor(s2 % 3600 / 60);
|
|
17626
|
+
const sec = s2 % 60;
|
|
17627
|
+
if (h2 > 0) return `${h2}h ${m2}m ${sec}s`;
|
|
17628
|
+
if (m2 > 0) return `${m2}m ${sec}s`;
|
|
17629
|
+
return `${sec}s`;
|
|
17630
|
+
}
|
|
17631
|
+
function saveSessionMemory() {
|
|
17632
|
+
const memDir = (0, import_path6.join)(BGI_DIR, "memory");
|
|
17633
|
+
if (!(0, import_fs6.existsSync)(memDir)) (0, import_fs6.mkdirSync)(memDir, { recursive: true });
|
|
17634
|
+
const dateStr = new Date(sessionStartTime).toISOString().slice(0, 10);
|
|
17635
|
+
const filename = (0, import_path6.join)(memDir, `${dateStr}-${sessionId}.md`);
|
|
17636
|
+
const lines = [
|
|
17637
|
+
`# \u4F1A\u8BDD\u8BB0\u5FC6 ${new Date(sessionStartTime).toLocaleString("zh-CN")}`,
|
|
17638
|
+
``,
|
|
17639
|
+
`- \u6A21\u578B: ${loadConfig().model}`,
|
|
17640
|
+
`- Token: \u8F93\u5165 ${sessionStats.inputTokens} / \u8F93\u51FA ${sessionStats.outputTokens}`,
|
|
17641
|
+
`- \u547D\u4EE4: ${sessionStats.successCmds} \u6210\u529F / ${sessionStats.failCmds} \u5931\u8D25`,
|
|
17642
|
+
``
|
|
17643
|
+
];
|
|
17644
|
+
let turnCount = 0;
|
|
17645
|
+
for (let i2 = 0; i2 < history.length; i2++) {
|
|
17646
|
+
const msg = history[i2];
|
|
17647
|
+
if (msg.role === "user" && typeof msg.content === "string") {
|
|
17648
|
+
turnCount++;
|
|
17649
|
+
const content = msg.content.slice(0, 500) + (msg.content.length > 500 ? "..." : "");
|
|
17650
|
+
lines.push(`## \u5BF9\u8BDD ${turnCount}`);
|
|
17651
|
+
lines.push(`**\u7528\u6237**: ${content}`);
|
|
17652
|
+
} else if (msg.role === "assistant" && typeof msg.content === "string") {
|
|
17653
|
+
const content = msg.content.slice(0, 500) + (msg.content.length > 500 ? "..." : "");
|
|
17654
|
+
lines.push(`**BGI**: ${content}`);
|
|
17655
|
+
lines.push(``);
|
|
17656
|
+
}
|
|
17657
|
+
}
|
|
17658
|
+
(0, import_fs6.writeFileSync)(filename, lines.join("\n"), "utf8");
|
|
17659
|
+
console.log(source_default.green(` \u2713 \u8BB0\u5FC6\u5DF2\u4FDD\u5B58: ${filename}`));
|
|
17660
|
+
}
|
|
17661
|
+
async function exitWithReport() {
|
|
17662
|
+
if (exiting) return;
|
|
17663
|
+
exiting = true;
|
|
17664
|
+
const runtime = formatDuration(Date.now() - sessionStartTime);
|
|
17665
|
+
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"));
|
|
17666
|
+
console.log(` \u8FD0\u884C\u65F6\u95F4: ${source_default.white(runtime)}`);
|
|
17667
|
+
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))}`);
|
|
17668
|
+
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")}`);
|
|
17669
|
+
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"));
|
|
17670
|
+
try {
|
|
17671
|
+
const ans = await question(rl, source_default.cyan("\n \u662F\u5426\u4FDD\u5B58\u672C\u6B21\u4F1A\u8BDD\u8BB0\u5FC6\uFF1F[y/N] "));
|
|
17672
|
+
if (ans.trim().toLowerCase() === "y") saveSessionMemory();
|
|
17673
|
+
} catch {
|
|
17674
|
+
}
|
|
17675
|
+
console.log(source_default.dim("\n\u518D\u89C1\uFF01"));
|
|
17676
|
+
process.exit(0);
|
|
17677
|
+
}
|
|
17678
|
+
let lastSigintCall = 0;
|
|
17679
|
+
function handleSigint() {
|
|
17680
|
+
const now = Date.now();
|
|
17681
|
+
if (now - lastSigintCall < 200) return;
|
|
17682
|
+
lastSigintCall = now;
|
|
17683
|
+
if (now - lastSigintTime < 2e3) {
|
|
17684
|
+
sigintHandling = false;
|
|
17685
|
+
exitWithReport().catch(() => process.exit(0));
|
|
17686
|
+
} else {
|
|
17687
|
+
lastSigintTime = now;
|
|
17688
|
+
sigintHandling = true;
|
|
17689
|
+
if (currentAbortController) {
|
|
17690
|
+
currentAbortController.abort();
|
|
17691
|
+
}
|
|
17692
|
+
process.stdout.write(source_default.yellow("\n\n [\u4EFB\u52A1\u5DF2\u4E2D\u65AD] \u518D\u6309\u4E00\u6B21 Ctrl+C \u9000\u51FA\n\n"));
|
|
17693
|
+
setTimeout(() => {
|
|
17694
|
+
sigintHandling = false;
|
|
17695
|
+
}, 500);
|
|
17696
|
+
}
|
|
17697
|
+
}
|
|
17698
|
+
rl.on("SIGINT", handleSigint);
|
|
17699
|
+
process.on("SIGINT", handleSigint);
|
|
17590
17700
|
while (true) {
|
|
17591
17701
|
let input;
|
|
17592
17702
|
const thinkIndicator = thinkMode ? source_default.yellow("[\u601D\u8003]") + " " : "";
|
|
@@ -17598,9 +17708,8 @@ async function main() {
|
|
|
17598
17708
|
const trimmed = input.trim();
|
|
17599
17709
|
if (!trimmed) continue;
|
|
17600
17710
|
if (["exit", "quit", "q", "/exit", "/quit"].includes(trimmed.toLowerCase())) {
|
|
17601
|
-
|
|
17602
|
-
|
|
17603
|
-
break;
|
|
17711
|
+
await exitWithReport();
|
|
17712
|
+
return;
|
|
17604
17713
|
}
|
|
17605
17714
|
if (trimmed.startsWith("/")) {
|
|
17606
17715
|
const result = await handleCommand(trimmed, rl, history, thinkMode, injectedSkills);
|
|
@@ -17656,7 +17765,14 @@ ${expanded}` : expanded;
|
|
|
17656
17765
|
history.push({ role: "user", content: userContent });
|
|
17657
17766
|
try {
|
|
17658
17767
|
const currentCfg = loadConfig();
|
|
17659
|
-
|
|
17768
|
+
currentAbortController = new AbortController();
|
|
17769
|
+
const reply = await chat(history, currentCfg, systemPrompt2, sessionStats, currentAbortController.signal);
|
|
17770
|
+
currentAbortController = null;
|
|
17771
|
+
if (!reply && history[history.length - 1]?.role === "user") {
|
|
17772
|
+
history.pop();
|
|
17773
|
+
console.log();
|
|
17774
|
+
continue;
|
|
17775
|
+
}
|
|
17660
17776
|
history.push({ role: "assistant", content: reply });
|
|
17661
17777
|
history = await maybeCompact(history, currentCfg);
|
|
17662
17778
|
autoSaveSession();
|
|
@@ -17671,7 +17787,13 @@ ${expanded}` : expanded;
|
|
|
17671
17787
|
[\u6FC0\u6D3B Skill: ${ids}]`));
|
|
17672
17788
|
}
|
|
17673
17789
|
} catch (err) {
|
|
17790
|
+
currentAbortController = null;
|
|
17674
17791
|
const msg = err instanceof Error ? err.message : String(err);
|
|
17792
|
+
if (err instanceof Error && (err.name === "AbortError" || msg.toLowerCase().includes("abort"))) {
|
|
17793
|
+
history.pop();
|
|
17794
|
+
console.log();
|
|
17795
|
+
continue;
|
|
17796
|
+
}
|
|
17675
17797
|
console.error(source_default.red(`
|
|
17676
17798
|
\u9519\u8BEF: ${msg}
|
|
17677
17799
|
`));
|
|
@@ -17679,6 +17801,7 @@ ${expanded}` : expanded;
|
|
|
17679
17801
|
}
|
|
17680
17802
|
console.log();
|
|
17681
17803
|
}
|
|
17804
|
+
await exitWithReport();
|
|
17682
17805
|
}
|
|
17683
17806
|
function question(rl, prompt) {
|
|
17684
17807
|
return new Promise((resolve4, reject) => {
|