chattercatcher 0.1.19 → 0.1.21

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
@@ -59,6 +59,9 @@ declare const appSecretsSchema: z.ZodObject<{
59
59
  multimodal: z.ZodPipe<z.ZodTransform<{}, unknown>, z.ZodObject<{
60
60
  apiKey: z.ZodDefault<z.ZodString>;
61
61
  }, z.core.$strip>>;
62
+ web: z.ZodPipe<z.ZodTransform<{}, unknown>, z.ZodObject<{
63
+ actionToken: z.ZodDefault<z.ZodString>;
64
+ }, z.core.$strip>>;
62
65
  }, z.core.$strip>;
63
66
  type AppConfig = z.infer<typeof appConfigSchema>;
64
67
  type AppSecrets = z.infer<typeof appSecretsSchema>;
@@ -83,11 +86,217 @@ declare function resolveEmbeddingApiKey(input: {
83
86
  llmApiKey: string;
84
87
  }): string;
85
88
 
89
+ interface ChatRecord {
90
+ id: string;
91
+ platform: string;
92
+ platformChatId: string;
93
+ name: string;
94
+ createdAt: string;
95
+ updatedAt: string;
96
+ }
97
+ interface MessageRecord {
98
+ id: string;
99
+ platform: string;
100
+ platformMessageId: string;
101
+ chatId: string;
102
+ senderId: string;
103
+ senderName: string;
104
+ messageType: string;
105
+ text: string;
106
+ rawPayloadJson: string;
107
+ sentAt: string;
108
+ receivedAt: string;
109
+ createdAt: string;
110
+ }
111
+ interface FileRecord {
112
+ messageId: string;
113
+ fileName: string;
114
+ sourcePath?: string;
115
+ storedPath?: string;
116
+ bytes?: number;
117
+ characters: number;
118
+ parser?: string;
119
+ parserWarnings?: string[];
120
+ importedAt: string;
121
+ }
122
+ interface IngestMessageInput {
123
+ platform: string;
124
+ platformChatId: string;
125
+ chatName: string;
126
+ platformMessageId: string;
127
+ senderId: string;
128
+ senderName: string;
129
+ messageType: string;
130
+ text: string;
131
+ rawPayload?: unknown;
132
+ sentAt: string;
133
+ }
134
+ interface CreateImageSummaryMessageInput {
135
+ sourceMessageId: string;
136
+ imageKey: string;
137
+ summary: string;
138
+ reason?: string;
139
+ multimodalModel: string;
140
+ generatedAt: string;
141
+ }
142
+ interface MessageSearchScope {
143
+ platform?: string;
144
+ platformChatId?: string;
145
+ }
146
+ interface MessageSearchResult {
147
+ chunkId: string;
148
+ messageId: string;
149
+ platform: string;
150
+ text: string;
151
+ score: number;
152
+ messageType: string;
153
+ chatName: string;
154
+ senderName: string;
155
+ sentAt: string;
156
+ }
157
+
158
+ type SourceType = "message" | "episode" | "file" | "image" | "audio" | "link" | "feishu_doc";
159
+ interface EvidenceSource {
160
+ type: SourceType;
161
+ label: string;
162
+ timestamp?: string;
163
+ sender?: string;
164
+ location?: string;
165
+ }
166
+ interface EvidenceBlock {
167
+ id: string;
168
+ text: string;
169
+ score: number;
170
+ source: EvidenceSource;
171
+ }
172
+ interface Citation {
173
+ marker: string;
174
+ evidenceId: string;
175
+ source: EvidenceSource;
176
+ text: string;
177
+ }
178
+ interface GroundedAnswer {
179
+ answer: string;
180
+ citations: Citation[];
181
+ }
182
+ interface ToolCall {
183
+ id: string;
184
+ name: string;
185
+ input: unknown;
186
+ }
187
+ interface ChatMessage {
188
+ role: "system" | "user" | "assistant" | "tool";
189
+ content: string;
190
+ toolCallId?: string;
191
+ toolCalls?: ToolCall[];
192
+ reasoningContent?: string;
193
+ }
194
+ interface ChatTool {
195
+ name: string;
196
+ description: string;
197
+ inputSchema: Record<string, unknown>;
198
+ }
199
+ interface ToolChatResult {
200
+ content: string;
201
+ toolCalls: ToolCall[];
202
+ reasoningContent?: string;
203
+ }
204
+ interface ChatModel {
205
+ complete(messages: ChatMessage[]): Promise<string>;
206
+ completeWithTools?(messages: ChatMessage[], tools: ChatTool[]): Promise<ToolChatResult>;
207
+ }
208
+
209
+ type RetrievalScope = MessageSearchScope;
210
+ interface Retriever {
211
+ retrieve(question: string, scope?: RetrievalScope): Promise<EvidenceBlock[]>;
212
+ }
213
+
214
+ interface RagSearchTool extends ChatTool {
215
+ execute(input: unknown): Promise<EvidenceBlock[]>;
216
+ }
217
+
218
+ interface GenerateCronJobMessageInput {
219
+ prompt: string;
220
+ model: ChatModel;
221
+ tools: RagSearchTool[];
222
+ now: Date;
223
+ maxModelTurns?: number;
224
+ maxToolCalls?: number;
225
+ }
226
+ declare function generateCronJobMessage(input: GenerateCronJobMessageInput): Promise<string>;
227
+
86
228
  type SqliteDatabase = Database.Database;
87
229
  declare function getDatabasePath(config: AppConfig): string;
88
230
  declare function openDatabase(config: AppConfig): SqliteDatabase;
89
231
  declare function migrateDatabase(database: SqliteDatabase): void;
90
232
 
233
+ type CronJobStatus = "active" | "deleted";
234
+ interface CronJobRecord {
235
+ id: string;
236
+ chatId: string;
237
+ createdByOpenId?: string;
238
+ schedule: string;
239
+ prompt: string;
240
+ status: CronJobStatus;
241
+ lastRunAt?: string;
242
+ nextRunAt: string;
243
+ lastError?: string;
244
+ createdAt: string;
245
+ updatedAt: string;
246
+ }
247
+ interface CronJobRepositoryOptions {
248
+ now?: () => Date;
249
+ }
250
+ declare class CronJobRepository {
251
+ private readonly database;
252
+ private readonly now;
253
+ constructor(database: SqliteDatabase, options?: CronJobRepositoryOptions);
254
+ create(input: {
255
+ chatId: string;
256
+ createdByOpenId?: string;
257
+ schedule: string;
258
+ prompt: string;
259
+ }): CronJobRecord;
260
+ get(id: string): CronJobRecord | null;
261
+ list(limit?: number): CronJobRecord[];
262
+ listByChat(chatId: string, limit?: number): CronJobRecord[];
263
+ listDue(now: Date, limit?: number): CronJobRecord[];
264
+ deleteByChat(id: string, chatId: string): boolean;
265
+ markSuccess(id: string, ranAt: Date): void;
266
+ markFailure(id: string, error: string, failedAt: Date): void;
267
+ private listByWhere;
268
+ }
269
+
270
+ declare function isValidCronSchedule(schedule: string): boolean;
271
+ declare function matchesCronSchedule(schedule: string, date: Date): boolean;
272
+ declare function getNextCronRun(schedule: string, after: Date): Date | null;
273
+
274
+ interface CronJobScheduler {
275
+ start(): void;
276
+ stop(): void;
277
+ runDueNow(): Promise<void>;
278
+ }
279
+ interface CreateCronJobSchedulerOptions {
280
+ repository: Pick<CronJobRepository, "listDue" | "markSuccess" | "markFailure">;
281
+ generateMessage: (job: CronJobRecord, now: Date) => Promise<string>;
282
+ sendTextToChat: (chatId: string, text: string) => Promise<void>;
283
+ now?: () => Date;
284
+ setIntervalFn?: typeof setInterval;
285
+ clearIntervalFn?: typeof clearInterval;
286
+ logger?: Pick<Console, "error">;
287
+ }
288
+ declare function createCronJobScheduler(options: CreateCronJobSchedulerOptions): CronJobScheduler;
289
+
290
+ interface CronJobTool extends ChatTool {
291
+ execute(input: unknown): Promise<string>;
292
+ }
293
+ interface CreateCronJobToolsInput {
294
+ repository: CronJobRepository;
295
+ chatId: string;
296
+ createdByOpenId?: string;
297
+ }
298
+ declare function createCronJobTools(input: CreateCronJobToolsInput): CronJobTool[];
299
+
91
300
  type DeleteTargetType = "message" | "chat" | "file";
92
301
  interface DeleteLocalDataResult {
93
302
  targetType: DeleteTargetType;
@@ -146,55 +355,6 @@ declare function restoreLocalData(input: {
146
355
  replace?: boolean;
147
356
  }): Promise<DataRestoreResult>;
148
357
 
149
- type SourceType = "message" | "episode" | "file" | "image" | "audio" | "link" | "feishu_doc";
150
- interface EvidenceSource {
151
- type: SourceType;
152
- label: string;
153
- timestamp?: string;
154
- sender?: string;
155
- location?: string;
156
- }
157
- interface EvidenceBlock {
158
- id: string;
159
- text: string;
160
- score: number;
161
- source: EvidenceSource;
162
- }
163
- interface Citation {
164
- marker: string;
165
- evidenceId: string;
166
- source: EvidenceSource;
167
- text: string;
168
- }
169
- interface GroundedAnswer {
170
- answer: string;
171
- citations: Citation[];
172
- }
173
- interface ToolCall {
174
- id: string;
175
- name: string;
176
- input: unknown;
177
- }
178
- interface ChatMessage {
179
- role: "system" | "user" | "assistant" | "tool";
180
- content: string;
181
- toolCallId?: string;
182
- toolCalls?: ToolCall[];
183
- }
184
- interface ChatTool {
185
- name: string;
186
- description: string;
187
- inputSchema: Record<string, unknown>;
188
- }
189
- interface ToolChatResult {
190
- content: string;
191
- toolCalls: ToolCall[];
192
- }
193
- interface ChatModel {
194
- complete(messages: ChatMessage[]): Promise<string>;
195
- completeWithTools?(messages: ChatMessage[], tools: ChatTool[]): Promise<ToolChatResult>;
196
- }
197
-
198
358
  interface ProcessEpisodesResult {
199
359
  created: number;
200
360
  }
@@ -206,71 +366,6 @@ declare function processEpisodesNow(input: {
206
366
  now?: Date;
207
367
  }): Promise<ProcessEpisodesResult>;
208
368
 
209
- interface ChatRecord {
210
- id: string;
211
- platform: string;
212
- platformChatId: string;
213
- name: string;
214
- createdAt: string;
215
- updatedAt: string;
216
- }
217
- interface MessageRecord {
218
- id: string;
219
- platform: string;
220
- platformMessageId: string;
221
- chatId: string;
222
- senderId: string;
223
- senderName: string;
224
- messageType: string;
225
- text: string;
226
- rawPayloadJson: string;
227
- sentAt: string;
228
- receivedAt: string;
229
- createdAt: string;
230
- }
231
- interface FileRecord {
232
- messageId: string;
233
- fileName: string;
234
- sourcePath?: string;
235
- storedPath?: string;
236
- bytes?: number;
237
- characters: number;
238
- parser?: string;
239
- parserWarnings?: string[];
240
- importedAt: string;
241
- }
242
- interface IngestMessageInput {
243
- platform: string;
244
- platformChatId: string;
245
- chatName: string;
246
- platformMessageId: string;
247
- senderId: string;
248
- senderName: string;
249
- messageType: string;
250
- text: string;
251
- rawPayload?: unknown;
252
- sentAt: string;
253
- }
254
- interface CreateImageSummaryMessageInput {
255
- sourceMessageId: string;
256
- imageKey: string;
257
- summary: string;
258
- reason?: string;
259
- multimodalModel: string;
260
- generatedAt: string;
261
- }
262
- interface MessageSearchResult {
263
- chunkId: string;
264
- messageId: string;
265
- platform: string;
266
- text: string;
267
- score: number;
268
- messageType: string;
269
- chatName: string;
270
- senderName: string;
271
- sentAt: string;
272
- }
273
-
274
369
  interface EpisodeMessage {
275
370
  id: string;
276
371
  chatId: string;
@@ -327,7 +422,7 @@ declare class EpisodeRepository {
327
422
  }): Promise<EpisodeSummaryRecord | undefined>;
328
423
  getEpisodeCount(): number;
329
424
  listRecentEpisodes(limit?: number): EpisodeListItem[];
330
- searchEpisodes(query: string, limit?: number): EpisodeSearchResult[];
425
+ searchEpisodes(query: string, limit?: number, scope?: MessageSearchScope): EpisodeSearchResult[];
331
426
  }
332
427
 
333
428
  declare function sanitizeEpisodeSummary(summary: string): string;
@@ -633,6 +728,12 @@ interface FeishuGatewayOptions {
633
728
  database: SqliteDatabase;
634
729
  };
635
730
  indexingScheduler?: IndexingScheduler;
731
+ cronJobProcessor?: {
732
+ database: SqliteDatabase;
733
+ model: ChatModel;
734
+ sender: Pick<MessageSender, "sendTextToChat">;
735
+ };
736
+ cronJobScheduler?: CronJobScheduler;
636
737
  wsClientFactory?: (params: {
637
738
  appId: string;
638
739
  appSecret: string;
@@ -675,6 +776,7 @@ declare class MessageRepository {
675
776
  listMessageChunksByMessageIds(messageIds: string[], limit?: number): MessageSearchResult[];
676
777
  searchMessages(query: string, limit?: number, options?: {
677
778
  excludeMessageIds?: string[];
779
+ scope?: MessageSearchScope;
678
780
  }): MessageSearchResult[];
679
781
  getChatCount(): number;
680
782
  getMessageCount(): number;
@@ -870,18 +972,15 @@ declare function formatCitations(citations: Citation[], options?: {
870
972
  maxTextLength?: number;
871
973
  }): string;
872
974
 
873
- interface Retriever {
874
- retrieve(question: string): Promise<EvidenceBlock[]>;
875
- }
876
-
877
975
  interface HybridRetrieverOptions {
878
976
  limit?: number;
977
+ scope?: RetrievalScope;
879
978
  }
880
979
  declare class HybridRetriever implements Retriever {
881
980
  private readonly retrievers;
882
981
  private readonly options;
883
982
  constructor(retrievers: Retriever[], options?: HybridRetrieverOptions);
884
- retrieve(question: string): Promise<EvidenceBlock[]>;
983
+ retrieve(question: string, scope?: RetrievalScope): Promise<EvidenceBlock[]>;
885
984
  }
886
985
 
887
986
  interface VectorRecord {
@@ -894,12 +993,12 @@ interface VectorSearchResult extends EvidenceBlock {
894
993
  }
895
994
  interface VectorStore {
896
995
  upsert(records: VectorRecord[]): Promise<void>;
897
- search(vector: number[], limit: number): Promise<VectorSearchResult[]>;
996
+ search(vector: number[], limit: number, scope?: MessageSearchScope): Promise<VectorSearchResult[]>;
898
997
  }
899
998
  declare class MemoryVectorStore implements VectorStore {
900
999
  private readonly records;
901
1000
  upsert(records: VectorRecord[]): Promise<void>;
902
- search(vector: number[], limit: number): Promise<VectorSearchResult[]>;
1001
+ search(vector: number[], limit: number, _scope?: MessageSearchScope): Promise<VectorSearchResult[]>;
903
1002
  }
904
1003
 
905
1004
  interface VectorIndexStats {
@@ -914,10 +1013,6 @@ declare function indexMessageChunks(input: {
914
1013
  messageIds?: string[];
915
1014
  }): Promise<VectorIndexStats>;
916
1015
 
917
- interface RagSearchTool extends ChatTool {
918
- execute(input: unknown): Promise<EvidenceBlock[]>;
919
- }
920
-
921
1016
  declare function hasEmbeddingConfig(config: AppConfig, secrets: AppSecrets): boolean;
922
1017
  declare function createHybridRetriever(input: {
923
1018
  config: AppConfig;
@@ -925,6 +1020,7 @@ declare function createHybridRetriever(input: {
925
1020
  database: SqliteDatabase;
926
1021
  messages: MessageRepository;
927
1022
  excludeMessageIds?: string[];
1023
+ scope?: MessageSearchScope;
928
1024
  }): Promise<{
929
1025
  retriever: Retriever;
930
1026
  close: () => void;
@@ -935,6 +1031,7 @@ declare function createAgenticRagSearchTools(input: {
935
1031
  database: SqliteDatabase;
936
1032
  messages: MessageRepository;
937
1033
  excludeMessageIds?: string[];
1034
+ scope?: MessageSearchScope;
938
1035
  }): Promise<{
939
1036
  tools: RagSearchTool[];
940
1037
  close: () => void;
@@ -962,7 +1059,7 @@ declare class MessageFtsRetriever implements Retriever {
962
1059
  constructor(messages: MessageRepository, options?: {
963
1060
  excludeMessageIds?: string[];
964
1061
  });
965
- retrieve(question: string): Promise<EvidenceBlock[]>;
1062
+ retrieve(question: string, scope?: RetrievalScope): Promise<EvidenceBlock[]>;
966
1063
  }
967
1064
 
968
1065
  interface AskWithRagInput {
@@ -977,10 +1074,10 @@ declare class VectorRetriever implements Retriever {
977
1074
  private readonly store;
978
1075
  private readonly limit;
979
1076
  constructor(embedding: EmbeddingModel, store: VectorStore, limit?: number);
980
- retrieve(question: string): Promise<EvidenceBlock[]>;
1077
+ retrieve(question: string, scope?: RetrievalScope): Promise<EvidenceBlock[]>;
981
1078
  }
982
1079
 
983
1080
  declare function createWebApp(config: AppConfig): FastifyInstance;
984
1081
  declare function startWebServer(config: AppConfig): Promise<void>;
985
1082
 
986
- export { type AppConfig, type AppSecrets, type AskWithRagInput, type BuildEvidencePromptOptions, type ChatMessage, type ChatModel, type ChatRecord, type ChatTool, type Citation, type CreateImageSummaryMessageInput, 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 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, createDefaultConfig, createDefaultSecrets, createEmbeddingModel, createFeishuEventDispatcher, createFeishuGateway, createHybridRetriever, createWebApp, deleteLocalData, describeSupportedParseTypes, ensureConfigFiles, exportLocalData, extractFeishuAttachment, followLogFile, formatCitation, formatCitations, formatDoctorChecks, generateGroundedAnswer, getDatabasePath, getFeishuQuestionDecision, getGatewayLogPath, getGatewayPidPath, getGatewayRuntimeState, getLogsDirectory, hasEmbeddingConfig, indexMessageChunks, ingestLocalFile, isFeishuMessageAddressedToBot, isProcessRunning, isSupportedParseFile, isSupportedTextFile, listLogFiles, loadConfig, loadSecrets, mapDomain, maskSecret, migrateDatabase, normalizeFeishuReceiveMessageEvent, normalizeLineCount, openDatabase, parseFileToText, processEpisodesNow, processMessagesNow, rankEvidenceForPrompt, readGatewayPidRecord, readLatestLogTail, readLogTail, removeGatewayPidRecord, resetConfigFiles, resolveEmbeddingApiKey, resolveLogPath, restoreLocalData, runDoctor, sanitizeEpisodeSummary, saveConfig, saveSecrets, startWebServer, stopGatewayProcess, summarizeEpisodeWindow, writeGatewayPidRecord };
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 };