@bolloon/bolloon-agent 0.3.5 → 0.3.7

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.
@@ -871,8 +871,8 @@
871
871
  cleanContent = cleanContent.substring(0, finalGenIdx).trim();
872
872
  }
873
873
  }
874
- const knownToolNames = ctx && ctx.knownToolNames || /* @__PURE__ */ new Set();
875
- const segments = segmentChatReply(cleanContent, { knownToolNames });
874
+ const knownToolNames2 = ctx && ctx.knownToolNames || /* @__PURE__ */ new Set();
875
+ const segments = segmentChatReply(cleanContent, { knownToolNames: knownToolNames2 });
876
876
  if (segments.length === 0) {
877
877
  return;
878
878
  }
@@ -1096,6 +1096,7 @@
1096
1096
  streamingText = "";
1097
1097
  mountStepTimeline(streamingMessageEl, currentChannelId2);
1098
1098
  container.appendChild(streamingMessageEl);
1099
+ flushStepEventBuffer(currentChannelId2, ctx);
1099
1100
  if (typeof ctx.setTimelineState === "function") {
1100
1101
  ctx.setTimelineState("streaming");
1101
1102
  }
@@ -1144,16 +1145,12 @@
1144
1145
  if (!data || !data.type) return;
1145
1146
  let target = streamingMessageEl && streamingMessageEl.isConnected ? streamingMessageEl : null;
1146
1147
  if (!target) {
1147
- const aiMsgs = container.querySelectorAll(".message-ai");
1148
- if (aiMsgs.length === 0) {
1149
- if (currentChannelId2) {
1150
- const buf = stepEventBuffer.get(currentChannelId2) || [];
1151
- buf.push(data);
1152
- stepEventBuffer.set(currentChannelId2, buf);
1153
- }
1154
- return;
1148
+ if (currentChannelId2) {
1149
+ const buf = stepEventBuffer.get(currentChannelId2) || [];
1150
+ buf.push(data);
1151
+ stepEventBuffer.set(currentChannelId2, buf);
1155
1152
  }
1156
- target = aiMsgs[aiMsgs.length - 1];
1153
+ return;
1157
1154
  }
1158
1155
  if (!target) return;
1159
1156
  const timeline = getStepTimeline(target);
@@ -1459,20 +1456,25 @@
1459
1456
  return {};
1460
1457
  }
1461
1458
  var MR_addMessage = (...args) => _getMR().addMessage?.(...args);
1459
+ var MR_handleStreamTokenEvent = (...args) => _getMR().handleStreamTokenEvent?.(...args);
1462
1460
  var MR_finalizeTimelineAsMessage = (...args) => _getMR().finalizeTimelineAsMessage?.(...args);
1463
1461
  var MR_handleStepEvent = (...args) => _getMR().handleStepEvent?.(...args);
1464
1462
  var MR_escapeHtml = (s) => _getMR().escapeHtml?.(s);
1465
1463
  var MR_hasStreamingText = () => _getMR().hasStreamingText?.() ?? false;
1466
1464
  var MR_replaceStreamingText = (text) => _getMR().replaceStreamingText?.(text);
1467
1465
  var MR_injectRecoveredText = (text, ctx) => _getMR().injectRecoveredText?.(text, ctx ?? getRendererCtx());
1466
+ var knownToolNames = /* @__PURE__ */ new Set();
1468
1467
  function getRendererCtx() {
1469
1468
  return {
1470
1469
  messagesEl,
1471
1470
  messagesContainers,
1472
1471
  currentChannelId,
1473
1472
  lastUsedJudgmentIds,
1473
+ knownToolNames,
1474
+ toolCallCallback: (tool, _hostEl) => {
1475
+ console.log("[toolCall]", tool.name, tool.args);
1476
+ },
1474
1477
  openJudgmentsModalWithFilter
1475
- // 引用 client.js 函数, 通过参数注入避免循环 import
1476
1478
  };
1477
1479
  }
1478
1480
  var messagesEl = document.getElementById("messages");
@@ -2313,6 +2315,9 @@ ${data.error || "channel not found"}`, "error");
2313
2315
  function addMessage2(content, type, save = true, container, usedJudgmentIds = [], timestamp = void 0) {
2314
2316
  return MR_addMessage(content, type, save, container, usedJudgmentIds, getRendererCtx(), timestamp);
2315
2317
  }
2318
+ function handleStreamTokenEvent2(data) {
2319
+ return MR_handleStreamTokenEvent(data, getRendererCtx());
2320
+ }
2316
2321
  function finalizeTimelineAsMessage2() {
2317
2322
  return MR_finalizeTimelineAsMessage(getRendererCtx());
2318
2323
  }
@@ -2595,7 +2600,7 @@ ${data.error || "channel not found"}`, "error");
2595
2600
  currentPreviewBubble = newPreview;
2596
2601
  }
2597
2602
  } else if (data.type === "stream") {
2598
- if (false) handleStreamTokenEvent(data);
2603
+ handleStreamTokenEvent2(data);
2599
2604
  } else if (data.type === "regenerating") {
2600
2605
  const messages = container.querySelectorAll(".message-ai");
2601
2606
  if (messages.length > 0) {
@@ -3379,6 +3384,15 @@ ${data.error || "channel not found"}`, "error");
3379
3384
  if (!themeData.agentId) {
3380
3385
  await saveTheme(themeData.theme, currentAgentId);
3381
3386
  }
3387
+ try {
3388
+ const res = await fetch("/api/tools");
3389
+ if (res.ok) {
3390
+ const toolIds = await res.json();
3391
+ knownToolNames = new Set(toolIds);
3392
+ }
3393
+ } catch (e) {
3394
+ console.warn("[init] \u83B7\u53D6\u5DE5\u5177\u5217\u8868\u5931\u8D25:", e);
3395
+ }
3382
3396
  await loadChannels();
3383
3397
  await checkApiConfig();
3384
3398
  if (channels.length > 0) {
@@ -9,6 +9,7 @@ import * as os from 'os';
9
9
  import * as crypto from 'crypto';
10
10
  import { validateMessageInput, validateChannelInput, healthCheck, } from './input-validator.js';
11
11
  import { segmentChatReply } from '../agents/chat-segmenter.js';
12
+ import { listTools } from '../llm/tool-manifest/index.js';
12
13
  import { registerJudgmentsRoutes } from './routes-judgments.js';
13
14
  import { registerLlmConfigRoutes } from './routes-llm-config.js';
14
15
  import { registerTaskRoutes } from './routes-tasks.js';
@@ -1964,6 +1965,9 @@ export async function createWebServer(port = 3000, options = {}) {
1964
1965
  app.get('/api/health', (_req, res) => {
1965
1966
  res.json(healthCheck(getPackageVersion()));
1966
1967
  });
1968
+ app.get('/api/tools', (_req, res) => {
1969
+ res.json(listTools().map(t => t.id));
1970
+ });
1967
1971
  // 2026-07-01 (v0.2.6): 前后端分离核心 — 后端切 LLM 输出为结构化 segments
1968
1972
  // - POST /api/segment-reply { reply, knownTools }
1969
1973
  // - 返回 ChatSegment[] (think / text / env_details / tool_call / final)
@@ -317,6 +317,7 @@ function handleStreamTokenEvent(data, ctx = { messagesEl: null, messagesContaine
317
317
  streamingText = "";
318
318
  mountStepTimeline(streamingMessageEl, currentChannelId);
319
319
  container.appendChild(streamingMessageEl);
320
+ flushStepEventBuffer(currentChannelId, ctx);
320
321
  if (typeof ctx.setTimelineState === "function") {
321
322
  ctx.setTimelineState("streaming");
322
323
  }
@@ -365,16 +366,12 @@ function handleStepEvent(data, ctx = { messagesEl: null, messagesContainers: /*
365
366
  if (!data || !data.type) return;
366
367
  let target = streamingMessageEl && streamingMessageEl.isConnected ? streamingMessageEl : null;
367
368
  if (!target) {
368
- const aiMsgs = container.querySelectorAll(".message-ai");
369
- if (aiMsgs.length === 0) {
370
- if (currentChannelId) {
371
- const buf = stepEventBuffer.get(currentChannelId) || [];
372
- buf.push(data);
373
- stepEventBuffer.set(currentChannelId, buf);
374
- }
375
- return;
369
+ if (currentChannelId) {
370
+ const buf = stepEventBuffer.get(currentChannelId) || [];
371
+ buf.push(data);
372
+ stepEventBuffer.set(currentChannelId, buf);
376
373
  }
377
- target = aiMsgs[aiMsgs.length - 1];
374
+ return;
378
375
  }
379
376
  if (!target) return;
380
377
  const timeline = getStepTimeline(target);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bolloon/bolloon-agent",
3
- "version": "0.3.5",
3
+ "version": "0.3.7",
4
4
  "type": "module",
5
5
  "description": "P2P AI Document Agent - 全局安装后执行 `bolloon` 启动产品",
6
6
  "main": "dist/cli-entry.js",
@@ -48,30 +48,30 @@
48
48
  "src/constraint-runtime"
49
49
  ],
50
50
  "dependencies": {
51
- "@bolloon/bolloon-agent": "^0.3.3",
51
+ "@bolloon/bolloon-agent": "^0.3.6",
52
52
  "@bolloon/constraint-runtime": "0.1.0",
53
- "@capacitor/core": "^8.4.1",
53
+ "@capacitor/core": "^8.4.2",
54
54
  "@capacitor/ios": "^8.4.1",
55
55
  "@chainsafe/libp2p-noise": "^17.0.0",
56
56
  "@chainsafe/libp2p-yamux": "^8.0.1",
57
57
  "@diap/sdk": "^0.1.10",
58
58
  "@libp2p/autonat": "^3.0.20",
59
- "@libp2p/circuit-relay-v2": "^4.2.5",
59
+ "@libp2p/circuit-relay-v2": "^4.2.9",
60
60
  "@libp2p/dcutr": "^3.0.20",
61
61
  "@libp2p/identify": "^4.1.6",
62
62
  "@libp2p/kad-dht": "^16.2.6",
63
63
  "@libp2p/tcp": "^11.0.20",
64
- "@libp2p/upnp-nat": "^4.0.20",
64
+ "@libp2p/upnp-nat": "^4.0.24",
65
65
  "@multiformats/multiaddr": "^13.0.3",
66
- "@noble/hashes": "^1.3.0",
66
+ "@noble/hashes": "^2.2.0",
67
67
  "@rayhanadev/iroh": "^0.1.1",
68
68
  "b4a": "^1.8.1",
69
69
  "dotenv": "^17.4.2",
70
- "esbuild": "^0.24.0",
70
+ "esbuild": "^0.28.1",
71
71
  "express": "^5.2.1",
72
72
  "libp2p": "^3.3.0",
73
73
  "mammoth": "^1.6.0",
74
- "pdf-parse": "^1.1.4",
74
+ "pdf-parse": "^2.4.5",
75
75
  "platform": "^1.3.6",
76
76
  "react": "^18.3.0",
77
77
  "react-dom": "^18.3.0",