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/index.d.ts CHANGED
@@ -189,6 +189,7 @@ interface ChatMessage {
189
189
  content: string;
190
190
  toolCallId?: string;
191
191
  toolCalls?: ToolCall[];
192
+ reasoningContent?: string;
192
193
  }
193
194
  interface ChatTool {
194
195
  name: string;
@@ -198,6 +199,7 @@ interface ChatTool {
198
199
  interface ToolChatResult {
199
200
  content: string;
200
201
  toolCalls: ToolCall[];
202
+ reasoningContent?: string;
201
203
  }
202
204
  interface ChatModel {
203
205
  complete(messages: ChatMessage[]): Promise<string>;
@@ -1075,7 +1077,10 @@ declare class VectorRetriever implements Retriever {
1075
1077
  retrieve(question: string, scope?: RetrievalScope): Promise<EvidenceBlock[]>;
1076
1078
  }
1077
1079
 
1078
- declare function createWebApp(config: AppConfig): FastifyInstance;
1079
- declare function startWebServer(config: AppConfig): Promise<void>;
1080
+ interface WebAppOptions {
1081
+ version?: string;
1082
+ }
1083
+ declare function createWebApp(config: AppConfig, options?: WebAppOptions): FastifyInstance;
1084
+ declare function startWebServer(config: AppConfig, options?: WebAppOptions): Promise<void>;
1080
1085
 
1081
- export { type AppConfig, type AppSecrets, type AskWithRagInput, type BuildEvidencePromptOptions, type ChatMessage, type ChatModel, type ChatRecord, type ChatTool, type Citation, type CreateImageSummaryMessageInput, type CronJobRecord, CronJobRepository, type CronJobScheduler, type CronJobStatus, type CronJobTool, type DataExportResult, type DataRestoreResult, type DeleteLocalDataResult, type DeleteTargetType, type DoctorCheck, type DoctorOptions, type DoctorStatus, type EmbeddingModel, type EpisodeListItem, type EpisodeMessage, EpisodeRepository, type EpisodeSearchResult, type EpisodeSummaryRecord, type EpisodeWindow, type EvidenceBlock, type EvidencePrompt, type EvidenceSource, type FeishuAttachmentMetadata, type FeishuDownloadResourceInput, type FeishuDownloadedResource, type FeishuGatewayOptions, type FeishuGatewayRuntime, FeishuMessageSender, type FeishuQuestionDecision, FeishuQuestionHandler, type FeishuQuestionHandlerOptions, type FeishuReceiveMessageEvent, FeishuResourceDownloader, type FileJobRecord, FileJobRepository, type FileJobStatus, type FileRecord, type GatewayAttachmentIngestResult, type GatewayIngestAndDownloadResult, type GatewayIngestResult, GatewayIngestor, type GatewayPidRecord, type GatewayRuntimeState, type GroundedAnswer, HybridRetriever, type HybridRetrieverOptions, type IngestLocalFileResult, type IngestMessageInput, type LogFileInfo, type LogTailResult, type ManualMessageIndexResult, MemoryVectorStore, MessageFtsRetriever, type MessageRecord, MessageRepository, type MessageSearchResult, type MessageSearchScope, type MessageSender, OpenAICompatibleChatModel, type OpenAICompatibleChatOptions, OpenAICompatibleEmbeddingModel, type OpenAICompatibleEmbeddingOptions, type ParsedFile, type ProcessEpisodesResult, type SourceType, type SqliteDatabase, type StopGatewayResult, type TextChunk, type ToolCall, type ToolChatResult, type VectorIndexStats, type VectorRecord, VectorRetriever, type VectorSearchResult, type VectorStore, appConfigSchema, appSecretsSchema, applySecretInput, askWithRag, buildEvidencePrompt, chunkText, cosineSimilarity, createAgenticRagSearchTools, createChatModel, createCronJobScheduler, createCronJobTools, createDefaultConfig, createDefaultSecrets, createEmbeddingModel, createFeishuEventDispatcher, createFeishuGateway, createHybridRetriever, createWebApp, deleteLocalData, describeSupportedParseTypes, ensureConfigFiles, exportLocalData, extractFeishuAttachment, followLogFile, formatCitation, formatCitations, formatDoctorChecks, generateCronJobMessage, generateGroundedAnswer, getDatabasePath, getFeishuQuestionDecision, getGatewayLogPath, getGatewayPidPath, getGatewayRuntimeState, getLogsDirectory, getNextCronRun, hasEmbeddingConfig, indexMessageChunks, ingestLocalFile, isFeishuMessageAddressedToBot, isProcessRunning, isSupportedParseFile, isSupportedTextFile, isValidCronSchedule, listLogFiles, loadConfig, loadSecrets, mapDomain, maskSecret, matchesCronSchedule, migrateDatabase, normalizeFeishuReceiveMessageEvent, normalizeLineCount, openDatabase, parseFileToText, processEpisodesNow, processMessagesNow, rankEvidenceForPrompt, readGatewayPidRecord, readLatestLogTail, readLogTail, removeGatewayPidRecord, resetConfigFiles, resolveEmbeddingApiKey, resolveLogPath, restoreLocalData, runDoctor, sanitizeEpisodeSummary, saveConfig, saveSecrets, startWebServer, stopGatewayProcess, summarizeEpisodeWindow, writeGatewayPidRecord };
1086
+ export { type AppConfig, type AppSecrets, type AskWithRagInput, type BuildEvidencePromptOptions, type ChatMessage, type ChatModel, type ChatRecord, type ChatTool, type Citation, type CreateImageSummaryMessageInput, type CronJobRecord, CronJobRepository, type CronJobScheduler, type CronJobStatus, type CronJobTool, type DataExportResult, type DataRestoreResult, type DeleteLocalDataResult, type DeleteTargetType, type DoctorCheck, type DoctorOptions, type DoctorStatus, type EmbeddingModel, type EpisodeListItem, type EpisodeMessage, EpisodeRepository, type EpisodeSearchResult, type EpisodeSummaryRecord, type EpisodeWindow, type EvidenceBlock, type EvidencePrompt, type EvidenceSource, type FeishuAttachmentMetadata, type FeishuDownloadResourceInput, type FeishuDownloadedResource, type FeishuGatewayOptions, type FeishuGatewayRuntime, FeishuMessageSender, type FeishuQuestionDecision, FeishuQuestionHandler, type FeishuQuestionHandlerOptions, type FeishuReceiveMessageEvent, FeishuResourceDownloader, type FileJobRecord, FileJobRepository, type FileJobStatus, type FileRecord, type GatewayAttachmentIngestResult, type GatewayIngestAndDownloadResult, type GatewayIngestResult, GatewayIngestor, type GatewayPidRecord, type GatewayRuntimeState, type GroundedAnswer, HybridRetriever, type HybridRetrieverOptions, type IngestLocalFileResult, type IngestMessageInput, type LogFileInfo, type LogTailResult, type ManualMessageIndexResult, MemoryVectorStore, MessageFtsRetriever, type MessageRecord, MessageRepository, type MessageSearchResult, type MessageSearchScope, type MessageSender, OpenAICompatibleChatModel, type OpenAICompatibleChatOptions, OpenAICompatibleEmbeddingModel, type OpenAICompatibleEmbeddingOptions, type ParsedFile, type ProcessEpisodesResult, type SourceType, type SqliteDatabase, type StopGatewayResult, type TextChunk, type ToolCall, type ToolChatResult, type VectorIndexStats, type VectorRecord, VectorRetriever, type VectorSearchResult, type VectorStore, type WebAppOptions, appConfigSchema, appSecretsSchema, applySecretInput, askWithRag, buildEvidencePrompt, chunkText, cosineSimilarity, createAgenticRagSearchTools, createChatModel, createCronJobScheduler, createCronJobTools, createDefaultConfig, createDefaultSecrets, createEmbeddingModel, createFeishuEventDispatcher, createFeishuGateway, createHybridRetriever, createWebApp, deleteLocalData, describeSupportedParseTypes, ensureConfigFiles, exportLocalData, extractFeishuAttachment, followLogFile, formatCitation, formatCitations, formatDoctorChecks, generateCronJobMessage, generateGroundedAnswer, getDatabasePath, getFeishuQuestionDecision, getGatewayLogPath, getGatewayPidPath, getGatewayRuntimeState, getLogsDirectory, getNextCronRun, hasEmbeddingConfig, indexMessageChunks, ingestLocalFile, isFeishuMessageAddressedToBot, isProcessRunning, isSupportedParseFile, isSupportedTextFile, isValidCronSchedule, listLogFiles, loadConfig, loadSecrets, mapDomain, maskSecret, matchesCronSchedule, migrateDatabase, normalizeFeishuReceiveMessageEvent, normalizeLineCount, openDatabase, parseFileToText, processEpisodesNow, processMessagesNow, rankEvidenceForPrompt, readGatewayPidRecord, readLatestLogTail, readLogTail, removeGatewayPidRecord, resetConfigFiles, resolveEmbeddingApiKey, resolveLogPath, restoreLocalData, runDoctor, sanitizeEpisodeSummary, saveConfig, saveSecrets, startWebServer, stopGatewayProcess, summarizeEpisodeWindow, writeGatewayPidRecord };
package/dist/index.js CHANGED
@@ -205,7 +205,7 @@ async function generateCronJobMessage(input) {
205
205
  let toolCallsUsed = 0;
206
206
  for (let turn = 0; turn < maxModelTurns; turn += 1) {
207
207
  const result = await input.model.completeWithTools(messages, input.tools);
208
- messages.push({ role: "assistant", content: result.content, toolCalls: result.toolCalls });
208
+ messages.push({ role: "assistant", content: result.content, toolCalls: result.toolCalls, reasoningContent: result.reasoningContent });
209
209
  if (result.toolCalls.length === 0) {
210
210
  break;
211
211
  }
@@ -1389,7 +1389,8 @@ function toOpenAIMessage(message) {
1389
1389
  arguments: JSON.stringify(toolCall.input)
1390
1390
  }
1391
1391
  }))
1392
- } : {}
1392
+ } : {},
1393
+ ...message.reasoningContent ? { reasoning_content: message.reasoningContent } : {}
1393
1394
  };
1394
1395
  }
1395
1396
  function toOpenAITool(tool) {
@@ -1435,7 +1436,8 @@ var OpenAICompatibleChatModel = class {
1435
1436
  throw new Error(`LLM \u8BF7\u6C42\u5931\u8D25\uFF1A${response.status} ${body}`);
1436
1437
  }
1437
1438
  const data = await response.json();
1438
- const content = data.choices?.[0]?.message?.content?.trim();
1439
+ const message = data.choices?.[0]?.message;
1440
+ const content = message?.content?.trim();
1439
1441
  if (!content) {
1440
1442
  throw new Error("LLM \u8FD4\u56DE\u4E3A\u7A7A\u3002");
1441
1443
  }
@@ -1467,7 +1469,8 @@ var OpenAICompatibleChatModel = class {
1467
1469
  const message = data.choices?.[0]?.message;
1468
1470
  return {
1469
1471
  content: message?.content ?? "",
1470
- toolCalls: parseToolCalls(message)
1472
+ toolCalls: parseToolCalls(message),
1473
+ reasoningContent: message?.reasoning_content ?? void 0
1471
1474
  };
1472
1475
  }
1473
1476
  };
@@ -3656,7 +3659,8 @@ async function runFeishuToolLoop(input) {
3656
3659
  messages.push({
3657
3660
  role: "assistant",
3658
3661
  content: assistantResult.content,
3659
- toolCalls: assistantResult.toolCalls
3662
+ toolCalls: assistantResult.toolCalls,
3663
+ reasoningContent: assistantResult.reasoningContent
3660
3664
  });
3661
3665
  if (assistantResult.toolCalls.length === 0) {
3662
3666
  return assistantResult.content || FEISHU_TOOL_LOOP_FALLBACK;
@@ -4934,6 +4938,7 @@ function buildHtml() {
4934
4938
  const gatewayClass = status.gateway.configured ? "status-ok" : "status-warn";
4935
4939
  metrics.innerHTML = [
4936
4940
  ["Gateway", formatGatewayValue(status.gateway), formatGatewayNote(status.gateway), gatewayClass],
4941
+ ["\u7248\u672C", status.version || "unknown", "\u5F53\u524D\u8FD0\u884C\u7248\u672C", ""],
4937
4942
  ["\u7FA4\u804A", status.data.chats, "\u672C\u5730\u7FA4\u804A\u6570", ""],
4938
4943
  ["\u6D88\u606F", status.data.messages, "\u5DF2\u5165\u5E93\u6D88\u606F", ""],
4939
4944
  ["\u4F1A\u8BDD\u8BB0\u5FC6", status.data.episodes, "\u5DF2\u751F\u6210\u6458\u8981", ""],
@@ -5127,25 +5132,39 @@ function buildHtml() {
5127
5132
  ");
5128
5133
  }
5129
5134
 
5135
+ async function fetchJson(path) {
5136
+ const response = await fetch(path);
5137
+ if (!response.ok) {
5138
+ const body = await response.text();
5139
+ throw new Error(path + " " + response.status + " " + body);
5140
+ }
5141
+ return response.json();
5142
+ }
5143
+
5144
+ function renderLoadError(element, error) {
5145
+ element.className = "empty";
5146
+ element.textContent = "\u52A0\u8F7D\u5931\u8D25\uFF1A" + (error instanceof Error ? error.message : String(error));
5147
+ }
5148
+
5149
+ async function loadSection(path, element, render) {
5150
+ try {
5151
+ render(await fetchJson(path));
5152
+ } catch (error) {
5153
+ renderLoadError(element, error);
5154
+ }
5155
+ }
5156
+
5130
5157
  async function load() {
5131
- const [status, recent, episodeList, chatList, fileList, jobList, qaLogList, cronJobList] = await Promise.all([
5132
- fetch("/api/status").then((response) => response.json()),
5133
- fetch("/api/messages/recent?limit=20").then((response) => response.json()),
5134
- fetch("/api/episodes?limit=10").then((response) => response.json()),
5135
- fetch("/api/chats").then((response) => response.json()),
5136
- fetch("/api/files").then((response) => response.json()),
5137
- fetch("/api/file-jobs").then((response) => response.json()),
5138
- fetch("/api/qa-logs?limit=10").then((response) => response.json()),
5139
- fetch("/api/cron-jobs").then((response) => response.json()),
5158
+ await Promise.all([
5159
+ loadSection("/api/status", metrics, renderMetrics),
5160
+ loadSection("/api/messages/recent?limit=20", messages, (data) => renderMessages(data.items)),
5161
+ loadSection("/api/episodes?limit=10", episodes, (data) => renderEpisodes(data.items)),
5162
+ loadSection("/api/chats", chats, (data) => renderChats(data.items)),
5163
+ loadSection("/api/files", files, (data) => renderFiles(data.items)),
5164
+ loadSection("/api/file-jobs", fileJobs, (data) => renderFileJobs(data.items)),
5165
+ loadSection("/api/qa-logs?limit=10", qaLogs, (data) => renderQaLogs(data.items)),
5166
+ loadSection("/api/cron-jobs", cronJobs, (data) => renderCronJobs(data.items)),
5140
5167
  ]);
5141
- renderMetrics(status);
5142
- renderMessages(recent.items);
5143
- renderEpisodes(episodeList.items);
5144
- renderChats(chatList.items);
5145
- renderFiles(fileList.items);
5146
- renderFileJobs(jobList.items);
5147
- renderQaLogs(qaLogList.items);
5148
- renderCronJobs(cronJobList.items);
5149
5168
  }
5150
5169
 
5151
5170
  async function processNow() {
@@ -5205,7 +5224,6 @@ function buildHtml() {
5205
5224
  }
5206
5225
  }, 5000);
5207
5226
  </script>
5208
- <script src="/app.js"></script>
5209
5227
  </body>
5210
5228
  </html>`;
5211
5229
  }
@@ -5223,13 +5241,10 @@ function isAuthorizedWebAction(request, token) {
5223
5241
  const provided = readHeader(request.headers["x-chattercatcher-web-token"]);
5224
5242
  return provided === token;
5225
5243
  }
5226
- function extractInlineScript(html) {
5227
- const match = /<script>([\s\S]*)<\/script>/.exec(html);
5228
- return match?.[1] ?? "";
5229
- }
5230
- function createWebApp(config) {
5244
+ function createWebApp(config, options = {}) {
5231
5245
  const app = Fastify({ logger: false });
5232
5246
  const database = openDatabase(config);
5247
+ const version = options.version ?? "unknown";
5233
5248
  const messages = new MessageRepository(database);
5234
5249
  const episodes = new EpisodeRepository(database);
5235
5250
  const fileJobs = new FileJobRepository(database);
@@ -5251,6 +5266,7 @@ function createWebApp(config) {
5251
5266
  await tokenReady;
5252
5267
  return {
5253
5268
  app: "ChatterCatcher",
5269
+ version,
5254
5270
  gateway: getGatewayStatus(config),
5255
5271
  data: {
5256
5272
  chats: messages.getChatCount(),
@@ -5348,23 +5364,20 @@ function createWebApp(config) {
5348
5364
  };
5349
5365
  }
5350
5366
  });
5351
- app.get("/app.js", async (_request, reply) => {
5352
- await tokenReady;
5353
- reply.type("application/javascript; charset=utf-8");
5354
- return extractInlineScript(buildHtml()).replaceAll("__WEB_ACTION_TOKEN__", webActionToken);
5355
- });
5356
5367
  app.get("/", async (_request, reply) => {
5368
+ await tokenReady;
5357
5369
  reply.type("text/html; charset=utf-8");
5358
- return buildHtml();
5370
+ return buildHtml().replaceAll("__WEB_ACTION_TOKEN__", webActionToken);
5359
5371
  });
5360
5372
  return app;
5361
5373
  }
5362
- async function startWebServer(config) {
5363
- const app = createWebApp(config);
5374
+ async function startWebServer(config, options = {}) {
5375
+ const app = createWebApp(config, options);
5364
5376
  await app.listen({ host: config.web.host, port: config.web.port });
5365
5377
  const address = app.server.address();
5366
5378
  const url = typeof address === "string" ? address : `http://${config.web.host}:${address?.port ?? config.web.port}`;
5367
- console.log(`ChatterCatcher Web UI: ${url}`);
5379
+ const versionText = options.version ? ` ${options.version}` : "";
5380
+ console.log(`ChatterCatcher Web UI${versionText}: ${url}`);
5368
5381
  }
5369
5382
  export {
5370
5383
  CronJobRepository,