@bgicli/bgicli 2.2.16 → 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 +127 -15
- 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.0";
|
|
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" },
|
|
@@ -17526,10 +17554,8 @@ async function main() {
|
|
|
17526
17554
|
historySize: 100
|
|
17527
17555
|
});
|
|
17528
17556
|
rl.on("close", () => {
|
|
17529
|
-
console.log(source_default.dim("\n\u518D\u89C1\uFF01"));
|
|
17530
17557
|
process.exit(0);
|
|
17531
17558
|
});
|
|
17532
|
-
process.on("SIGINT", () => rl.close());
|
|
17533
17559
|
await firstRunIfNeeded(rl);
|
|
17534
17560
|
const cfg = loadConfig();
|
|
17535
17561
|
const prov = PROVIDERS[cfg.provider];
|
|
@@ -17587,6 +17613,79 @@ async function main() {
|
|
|
17587
17613
|
}
|
|
17588
17614
|
let lastCheckpointMsgCount = 0;
|
|
17589
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
|
+
});
|
|
17590
17689
|
while (true) {
|
|
17591
17690
|
let input;
|
|
17592
17691
|
const thinkIndicator = thinkMode ? source_default.yellow("[\u601D\u8003]") + " " : "";
|
|
@@ -17598,9 +17697,8 @@ async function main() {
|
|
|
17598
17697
|
const trimmed = input.trim();
|
|
17599
17698
|
if (!trimmed) continue;
|
|
17600
17699
|
if (["exit", "quit", "q", "/exit", "/quit"].includes(trimmed.toLowerCase())) {
|
|
17601
|
-
|
|
17602
|
-
|
|
17603
|
-
break;
|
|
17700
|
+
await exitWithReport();
|
|
17701
|
+
return;
|
|
17604
17702
|
}
|
|
17605
17703
|
if (trimmed.startsWith("/")) {
|
|
17606
17704
|
const result = await handleCommand(trimmed, rl, history, thinkMode, injectedSkills);
|
|
@@ -17656,7 +17754,14 @@ ${expanded}` : expanded;
|
|
|
17656
17754
|
history.push({ role: "user", content: userContent });
|
|
17657
17755
|
try {
|
|
17658
17756
|
const currentCfg = loadConfig();
|
|
17659
|
-
|
|
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
|
+
}
|
|
17660
17765
|
history.push({ role: "assistant", content: reply });
|
|
17661
17766
|
history = await maybeCompact(history, currentCfg);
|
|
17662
17767
|
autoSaveSession();
|
|
@@ -17671,7 +17776,13 @@ ${expanded}` : expanded;
|
|
|
17671
17776
|
[\u6FC0\u6D3B Skill: ${ids}]`));
|
|
17672
17777
|
}
|
|
17673
17778
|
} catch (err) {
|
|
17779
|
+
currentAbortController = null;
|
|
17674
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
|
+
}
|
|
17675
17786
|
console.error(source_default.red(`
|
|
17676
17787
|
\u9519\u8BEF: ${msg}
|
|
17677
17788
|
`));
|
|
@@ -17679,6 +17790,7 @@ ${expanded}` : expanded;
|
|
|
17679
17790
|
}
|
|
17680
17791
|
console.log();
|
|
17681
17792
|
}
|
|
17793
|
+
await exitWithReport();
|
|
17682
17794
|
}
|
|
17683
17795
|
function question(rl, prompt) {
|
|
17684
17796
|
return new Promise((resolve4, reject) => {
|