chattercatcher 0.1.20 → 0.1.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/cli.js CHANGED
@@ -8,7 +8,7 @@ import fs14 from "fs/promises";
8
8
  // package.json
9
9
  var package_default = {
10
10
  name: "chattercatcher",
11
- version: "0.1.20",
11
+ version: "0.1.22",
12
12
  description: "\u672C\u5730\u4F18\u5148\u7684\u98DE\u4E66/Lark \u5BB6\u5EAD\u7FA4\u77E5\u8BC6\u5E93\u673A\u5668\u4EBA",
13
13
  type: "module",
14
14
  main: "dist/index.js",
@@ -983,7 +983,8 @@ function toOpenAIMessage(message) {
983
983
  arguments: JSON.stringify(toolCall.input)
984
984
  }
985
985
  }))
986
- } : {}
986
+ } : {},
987
+ ...message.reasoningContent ? { reasoning_content: message.reasoningContent } : {}
987
988
  };
988
989
  }
989
990
  function toOpenAITool(tool) {
@@ -1029,7 +1030,8 @@ var OpenAICompatibleChatModel = class {
1029
1030
  throw new Error(`LLM \u8BF7\u6C42\u5931\u8D25\uFF1A${response.status} ${body}`);
1030
1031
  }
1031
1032
  const data2 = await response.json();
1032
- const content = data2.choices?.[0]?.message?.content?.trim();
1033
+ const message = data2.choices?.[0]?.message;
1034
+ const content = message?.content?.trim();
1033
1035
  if (!content) {
1034
1036
  throw new Error("LLM \u8FD4\u56DE\u4E3A\u7A7A\u3002");
1035
1037
  }
@@ -1061,7 +1063,8 @@ var OpenAICompatibleChatModel = class {
1061
1063
  const message = data2.choices?.[0]?.message;
1062
1064
  return {
1063
1065
  content: message?.content ?? "",
1064
- toolCalls: parseToolCalls(message)
1066
+ toolCalls: parseToolCalls(message),
1067
+ reasoningContent: message?.reasoning_content ?? void 0
1065
1068
  };
1066
1069
  }
1067
1070
  };
@@ -3027,7 +3030,7 @@ async function generateCronJobMessage(input2) {
3027
3030
  let toolCallsUsed = 0;
3028
3031
  for (let turn = 0; turn < maxModelTurns; turn += 1) {
3029
3032
  const result = await input2.model.completeWithTools(messages, input2.tools);
3030
- messages.push({ role: "assistant", content: result.content, toolCalls: result.toolCalls });
3033
+ messages.push({ role: "assistant", content: result.content, toolCalls: result.toolCalls, reasoningContent: result.reasoningContent });
3031
3034
  if (result.toolCalls.length === 0) {
3032
3035
  break;
3033
3036
  }
@@ -3801,7 +3804,8 @@ async function runFeishuToolLoop(input2) {
3801
3804
  messages.push({
3802
3805
  role: "assistant",
3803
3806
  content: assistantResult.content,
3804
- toolCalls: assistantResult.toolCalls
3807
+ toolCalls: assistantResult.toolCalls,
3808
+ reasoningContent: assistantResult.reasoningContent
3805
3809
  });
3806
3810
  if (assistantResult.toolCalls.length === 0) {
3807
3811
  return assistantResult.content || FEISHU_TOOL_LOOP_FALLBACK;
@@ -5356,6 +5360,7 @@ function buildHtml() {
5356
5360
  const gatewayClass = status.gateway.configured ? "status-ok" : "status-warn";
5357
5361
  metrics.innerHTML = [
5358
5362
  ["Gateway", formatGatewayValue(status.gateway), formatGatewayNote(status.gateway), gatewayClass],
5363
+ ["\u7248\u672C", status.version || "unknown", "\u5F53\u524D\u8FD0\u884C\u7248\u672C", ""],
5359
5364
  ["\u7FA4\u804A", status.data.chats, "\u672C\u5730\u7FA4\u804A\u6570", ""],
5360
5365
  ["\u6D88\u606F", status.data.messages, "\u5DF2\u5165\u5E93\u6D88\u606F", ""],
5361
5366
  ["\u4F1A\u8BDD\u8BB0\u5FC6", status.data.episodes, "\u5DF2\u751F\u6210\u6458\u8981", ""],
@@ -5549,25 +5554,39 @@ function buildHtml() {
5549
5554
  ");
5550
5555
  }
5551
5556
 
5557
+ async function fetchJson(path) {
5558
+ const response = await fetch(path);
5559
+ if (!response.ok) {
5560
+ const body = await response.text();
5561
+ throw new Error(path + " " + response.status + " " + body);
5562
+ }
5563
+ return response.json();
5564
+ }
5565
+
5566
+ function renderLoadError(element, error) {
5567
+ element.className = "empty";
5568
+ element.textContent = "\u52A0\u8F7D\u5931\u8D25\uFF1A" + (error instanceof Error ? error.message : String(error));
5569
+ }
5570
+
5571
+ async function loadSection(path, element, render) {
5572
+ try {
5573
+ render(await fetchJson(path));
5574
+ } catch (error) {
5575
+ renderLoadError(element, error);
5576
+ }
5577
+ }
5578
+
5552
5579
  async function load() {
5553
- const [status, recent, episodeList, chatList, fileList, jobList, qaLogList, cronJobList] = await Promise.all([
5554
- fetch("/api/status").then((response) => response.json()),
5555
- fetch("/api/messages/recent?limit=20").then((response) => response.json()),
5556
- fetch("/api/episodes?limit=10").then((response) => response.json()),
5557
- fetch("/api/chats").then((response) => response.json()),
5558
- fetch("/api/files").then((response) => response.json()),
5559
- fetch("/api/file-jobs").then((response) => response.json()),
5560
- fetch("/api/qa-logs?limit=10").then((response) => response.json()),
5561
- fetch("/api/cron-jobs").then((response) => response.json()),
5580
+ await Promise.all([
5581
+ loadSection("/api/status", metrics, renderMetrics),
5582
+ loadSection("/api/messages/recent?limit=20", messages, (data) => renderMessages(data.items)),
5583
+ loadSection("/api/episodes?limit=10", episodes, (data) => renderEpisodes(data.items)),
5584
+ loadSection("/api/chats", chats, (data) => renderChats(data.items)),
5585
+ loadSection("/api/files", files, (data) => renderFiles(data.items)),
5586
+ loadSection("/api/file-jobs", fileJobs, (data) => renderFileJobs(data.items)),
5587
+ loadSection("/api/qa-logs?limit=10", qaLogs, (data) => renderQaLogs(data.items)),
5588
+ loadSection("/api/cron-jobs", cronJobs, (data) => renderCronJobs(data.items)),
5562
5589
  ]);
5563
- renderMetrics(status);
5564
- renderMessages(recent.items);
5565
- renderEpisodes(episodeList.items);
5566
- renderChats(chatList.items);
5567
- renderFiles(fileList.items);
5568
- renderFileJobs(jobList.items);
5569
- renderQaLogs(qaLogList.items);
5570
- renderCronJobs(cronJobList.items);
5571
5590
  }
5572
5591
 
5573
5592
  async function processNow() {
@@ -5627,7 +5646,6 @@ function buildHtml() {
5627
5646
  }
5628
5647
  }, 5000);
5629
5648
  </script>
5630
- <script src="/app.js"></script>
5631
5649
  </body>
5632
5650
  </html>`;
5633
5651
  }
@@ -5645,13 +5663,10 @@ function isAuthorizedWebAction(request, token) {
5645
5663
  const provided = readHeader(request.headers["x-chattercatcher-web-token"]);
5646
5664
  return provided === token;
5647
5665
  }
5648
- function extractInlineScript(html) {
5649
- const match = /<script>([\s\S]*)<\/script>/.exec(html);
5650
- return match?.[1] ?? "";
5651
- }
5652
- function createWebApp(config) {
5666
+ function createWebApp(config, options = {}) {
5653
5667
  const app = Fastify({ logger: false });
5654
5668
  const database = openDatabase(config);
5669
+ const version = options.version ?? "unknown";
5655
5670
  const messages = new MessageRepository(database);
5656
5671
  const episodes = new EpisodeRepository(database);
5657
5672
  const fileJobs = new FileJobRepository(database);
@@ -5673,6 +5688,7 @@ function createWebApp(config) {
5673
5688
  await tokenReady;
5674
5689
  return {
5675
5690
  app: "ChatterCatcher",
5691
+ version,
5676
5692
  gateway: getGatewayStatus(config),
5677
5693
  data: {
5678
5694
  chats: messages.getChatCount(),
@@ -5770,23 +5786,20 @@ function createWebApp(config) {
5770
5786
  };
5771
5787
  }
5772
5788
  });
5773
- app.get("/app.js", async (_request, reply) => {
5774
- await tokenReady;
5775
- reply.type("application/javascript; charset=utf-8");
5776
- return extractInlineScript(buildHtml()).replaceAll("__WEB_ACTION_TOKEN__", webActionToken);
5777
- });
5778
5789
  app.get("/", async (_request, reply) => {
5790
+ await tokenReady;
5779
5791
  reply.type("text/html; charset=utf-8");
5780
- return buildHtml();
5792
+ return buildHtml().replaceAll("__WEB_ACTION_TOKEN__", webActionToken);
5781
5793
  });
5782
5794
  return app;
5783
5795
  }
5784
- async function startWebServer(config) {
5785
- const app = createWebApp(config);
5796
+ async function startWebServer(config, options = {}) {
5797
+ const app = createWebApp(config, options);
5786
5798
  await app.listen({ host: config.web.host, port: config.web.port });
5787
5799
  const address = app.server.address();
5788
5800
  const url = typeof address === "string" ? address : `http://${config.web.host}:${address?.port ?? config.web.port}`;
5789
- console.log(`ChatterCatcher Web UI: ${url}`);
5801
+ const versionText = options.version ? ` ${options.version}` : "";
5802
+ console.log(`ChatterCatcher Web UI${versionText}: ${url}`);
5790
5803
  }
5791
5804
 
5792
5805
  // src/cli.ts
@@ -5965,7 +5978,7 @@ async function startGatewayForegroundCommand() {
5965
5978
  });
5966
5979
  console.log(status.message);
5967
5980
  console.log("\u672C\u5730 Web UI \u4ECD\u4F1A\u542F\u52A8\uFF0C\u65B9\u4FBF\u7EE7\u7EED\u914D\u7F6E\u3002");
5968
- await startWebServer(config);
5981
+ await startWebServer(config, { version: package_default.version });
5969
5982
  return;
5970
5983
  }
5971
5984
  await tryEnsureFeishuBotOpenId(config, secrets);
@@ -6028,7 +6041,7 @@ async function startGatewayForegroundCommand() {
6028
6041
  console.log(status.message);
6029
6042
  try {
6030
6043
  await gatewayRuntime.start();
6031
- await startWebServer(config);
6044
+ await startWebServer(config, { version: package_default.version });
6032
6045
  } catch (error) {
6033
6046
  cleanup();
6034
6047
  throw error;
@@ -6067,7 +6080,7 @@ gateway.command("restart").description("\u91CD\u542F Gateway").action(async () =
6067
6080
  var web = program.command("web").description("\u7BA1\u7406\u672C\u5730 Web UI");
6068
6081
  web.command("start").description("\u542F\u52A8\u672C\u5730 Web UI").action(async () => {
6069
6082
  const config = await loadConfig();
6070
- await startWebServer(config);
6083
+ await startWebServer(config, { version: package_default.version });
6071
6084
  });
6072
6085
  var data = program.command("data").description("\u7BA1\u7406\u672C\u5730\u77E5\u8BC6\u5E93\u6570\u636E");
6073
6086
  async function deleteDataCommand(targetType, targetId, options) {