chattercatcher 0.1.21 → 0.1.23

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
@@ -1077,7 +1077,10 @@ declare class VectorRetriever implements Retriever {
1077
1077
  retrieve(question: string, scope?: RetrievalScope): Promise<EvidenceBlock[]>;
1078
1078
  }
1079
1079
 
1080
- declare function createWebApp(config: AppConfig): FastifyInstance;
1081
- 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>;
1082
1085
 
1083
- 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
@@ -4938,6 +4938,7 @@ function buildHtml() {
4938
4938
  const gatewayClass = status.gateway.configured ? "status-ok" : "status-warn";
4939
4939
  metrics.innerHTML = [
4940
4940
  ["Gateway", formatGatewayValue(status.gateway), formatGatewayNote(status.gateway), gatewayClass],
4941
+ ["\u7248\u672C", status.version || "unknown", "\u5F53\u524D\u8FD0\u884C\u7248\u672C", ""],
4941
4942
  ["\u7FA4\u804A", status.data.chats, "\u672C\u5730\u7FA4\u804A\u6570", ""],
4942
4943
  ["\u6D88\u606F", status.data.messages, "\u5DF2\u5165\u5E93\u6D88\u606F", ""],
4943
4944
  ["\u4F1A\u8BDD\u8BB0\u5FC6", status.data.episodes, "\u5DF2\u751F\u6210\u6458\u8981", ""],
@@ -5117,45 +5118,53 @@ function buildHtml() {
5117
5118
  " <span>" + escapeHtml(item.status) + "</span>",
5118
5119
  " <span>" + escapeHtml(citationCount) + " \u6761\u5F15\u7528</span>",
5119
5120
  " </div>",
5120
- " <div class="message-body"><strong>\u95EE\uFF1A</strong>" + escapeHtml(item.question) + "</div>",
5121
- " <div class="message-body"><strong>\u7B54\uFF1A</strong>" + escapeHtml(item.answer) + "</div>",
5121
+ " <div class=\\"message-body\\"><strong>\u95EE\uFF1A</strong>" + escapeHtml(item.question) + "</div>",
5122
+ " <div class=\\"message-body\\"><strong>\u7B54\uFF1A</strong>" + escapeHtml(item.answer) + "</div>",
5122
5123
  "</article>",
5123
- ].join("
5124
- ");
5124
+ ].join("\\n");
5125
5125
  });
5126
5126
  qaLogs.innerHTML = [
5127
5127
  '<div class="message-list">',
5128
5128
  rows.join(""),
5129
5129
  "</div>",
5130
- ].join("
5131
- ");
5130
+ ].join("\\n");
5132
5131
  }
5133
5132
 
5134
- async function load() {
5133
+ async function fetchJson(path) {
5134
+ const response = await fetch(path);
5135
+ if (!response.ok) {
5136
+ const body = await response.text();
5137
+ throw new Error(path + " " + response.status + " " + body);
5138
+ }
5139
+ return response.json();
5140
+ }
5141
+
5142
+ function renderLoadError(element, error) {
5143
+ element.className = "empty";
5144
+ element.textContent = "\u52A0\u8F7D\u5931\u8D25\uFF1A" + (error instanceof Error ? error.message : String(error));
5145
+ }
5146
+
5147
+ async function loadSection(path, element, render) {
5135
5148
  try {
5136
- const [status, recent, episodeList, chatList, fileList, jobList, qaLogList, cronJobList] = await Promise.all([
5137
- fetch("/api/status").then((response) => response.json()),
5138
- fetch("/api/messages/recent?limit=20").then((response) => response.json()),
5139
- fetch("/api/episodes?limit=10").then((response) => response.json()),
5140
- fetch("/api/chats").then((response) => response.json()),
5141
- fetch("/api/files").then((response) => response.json()),
5142
- fetch("/api/file-jobs").then((response) => response.json()),
5143
- fetch("/api/qa-logs?limit=10").then((response) => response.json()),
5144
- fetch("/api/cron-jobs").then((response) => response.json()),
5145
- ]);
5146
- renderMetrics(status);
5147
- renderMessages(recent.items);
5148
- renderEpisodes(episodeList.items);
5149
- renderChats(chatList.items);
5150
- renderFiles(fileList.items);
5151
- renderFileJobs(jobList.items);
5152
- renderQaLogs(qaLogList.items);
5153
- renderCronJobs(cronJobList.items);
5149
+ render(await fetchJson(path));
5154
5150
  } catch (error) {
5155
- metrics.innerHTML = '<div class="empty">\u6570\u636E\u52A0\u8F7D\u5931\u8D25\uFF1A' + escapeHtml(error instanceof Error ? error.message : String(error)) + '</div>';
5151
+ renderLoadError(element, error);
5156
5152
  }
5157
5153
  }
5158
5154
 
5155
+ async function load() {
5156
+ await Promise.all([
5157
+ loadSection("/api/status", metrics, renderMetrics),
5158
+ loadSection("/api/messages/recent?limit=20", messages, (data) => renderMessages(data.items)),
5159
+ loadSection("/api/episodes?limit=10", episodes, (data) => renderEpisodes(data.items)),
5160
+ loadSection("/api/chats", chats, (data) => renderChats(data.items)),
5161
+ loadSection("/api/files", files, (data) => renderFiles(data.items)),
5162
+ loadSection("/api/file-jobs", fileJobs, (data) => renderFileJobs(data.items)),
5163
+ loadSection("/api/qa-logs?limit=10", qaLogs, (data) => renderQaLogs(data.items)),
5164
+ loadSection("/api/cron-jobs", cronJobs, (data) => renderCronJobs(data.items)),
5165
+ ]);
5166
+ }
5167
+
5159
5168
  async function processNow() {
5160
5169
  processMessages.disabled = true;
5161
5170
  actionStatus.textContent = "\u6B63\u5728\u5904\u7406\u6D88\u606F\u7D22\u5F15...";
@@ -5230,9 +5239,10 @@ function isAuthorizedWebAction(request, token) {
5230
5239
  const provided = readHeader(request.headers["x-chattercatcher-web-token"]);
5231
5240
  return provided === token;
5232
5241
  }
5233
- function createWebApp(config) {
5242
+ function createWebApp(config, options = {}) {
5234
5243
  const app = Fastify({ logger: false });
5235
5244
  const database = openDatabase(config);
5245
+ const version = options.version ?? "unknown";
5236
5246
  const messages = new MessageRepository(database);
5237
5247
  const episodes = new EpisodeRepository(database);
5238
5248
  const fileJobs = new FileJobRepository(database);
@@ -5254,6 +5264,7 @@ function createWebApp(config) {
5254
5264
  await tokenReady;
5255
5265
  return {
5256
5266
  app: "ChatterCatcher",
5267
+ version,
5257
5268
  gateway: getGatewayStatus(config),
5258
5269
  data: {
5259
5270
  chats: messages.getChatCount(),
@@ -5358,12 +5369,13 @@ function createWebApp(config) {
5358
5369
  });
5359
5370
  return app;
5360
5371
  }
5361
- async function startWebServer(config) {
5362
- const app = createWebApp(config);
5372
+ async function startWebServer(config, options = {}) {
5373
+ const app = createWebApp(config, options);
5363
5374
  await app.listen({ host: config.web.host, port: config.web.port });
5364
5375
  const address = app.server.address();
5365
5376
  const url = typeof address === "string" ? address : `http://${config.web.host}:${address?.port ?? config.web.port}`;
5366
- console.log(`ChatterCatcher Web UI: ${url}`);
5377
+ const versionText = options.version ? ` ${options.version}` : "";
5378
+ console.log(`ChatterCatcher Web UI${versionText}: ${url}`);
5367
5379
  }
5368
5380
  export {
5369
5381
  CronJobRepository,