import Database from "better-sqlite3"; import type { AgentBackendType } from "../config.js"; import { type CollabState } from "../core/collab-loop.js"; export declare const LATEST_SCHEMA_VERSION: number; export declare const ROLLBACK_COMPATIBLE_SCHEMA_VERSIONS: readonly [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]; export declare const LATEST_TRANSPORT_SCHEMA_VERSION: number; export declare function initDatabase(dbPath: string): Database.Database; export declare function getBotRuntimeBackend(db: Database.Database, botName: string): AgentBackendType | undefined; /** 原子地领取某个 Bot 某项权限在某个自然日的一次提示额度。 */ export declare function claimDailyBotPermissionWarning(db: Database.Database, botName: string, permission: string, warnedDate: string): boolean; export interface BotRuntimeState { backendType?: AgentBackendType; model?: string; /** 推理强度运行时选择(low/medium/high/xhigh/max),backend 支持时生效 */ effort?: string; } export interface BotBackendModelState { model?: string; effort?: string; } export interface ScopeRuntimeConfig extends BotBackendModelState { backendType: AgentBackendType; } export type RuntimeEventName = "started" | "stage_changed" | "timeout" | "failed" | "stopped" | "done" | "failed_by_restart"; export interface RuntimeEventInput { botId: string; chatId: string; threadId?: string; runId: string; messageIds: number[]; stage: string; event: RuntimeEventName; error?: string; elapsedMs?: number; } export interface RuntimeEventRow extends RuntimeEventInput { id: number; createdAt: string; } export interface RuntimeEventQuery { botId?: string; chatId?: string; threadId?: string; runId?: string; limit?: number; } export declare function getBotRuntimeState(db: Database.Database, botName: string): BotRuntimeState | undefined; export declare function setBotRuntimeState(db: Database.Database, botName: string, state: BotRuntimeState): void; export declare function setBotRuntimeBackend(db: Database.Database, botName: string, backendType: AgentBackendType): void; export declare function getBotBackendModelState(db: Database.Database, botName: string, backendType: AgentBackendType): BotBackendModelState | undefined; export declare function setBotBackendModelState(db: Database.Database, botName: string, backendType: AgentBackendType, state: BotBackendModelState): void; export declare function clearBotRuntimeModels(db: Database.Database, botName: string): void; /** 清除某个 backend 的运行时 effort 选择(/effort reset)。 */ export declare function clearBotBackendEffort(db: Database.Database, botName: string, backendType: AgentBackendType): void; /** 用户的私聊 chat id。配置回退已改成 Bot 默认整包,这段只留给查私聊会话。 */ export declare function findP2pChatIdForUser(db: Database.Database, userId: string): string | undefined; export declare function getScopeRuntimeConfig(db: Database.Database, botName: string, scopeKey: string): ScopeRuntimeConfig | undefined; export declare function setScopeRuntimeConfig(db: Database.Database, botName: string, scopeKey: string, config: ScopeRuntimeConfig): void; /** * 为首次使用的 scope 固化解析后的配置,但不覆盖并发写入的显式覆盖。 * 与 setScopeRuntimeConfig 不同,这个函数只负责 scope 行,不会更新 Bot 默认。 */ export declare function ensureScopeRuntimeConfig(db: Database.Database, botName: string, scopeKey: string, config: ScopeRuntimeConfig): ScopeRuntimeConfig; export declare function deleteScopeRuntimeConfig(db: Database.Database, botName: string, scopeKey: string): void; /** 本地 Bot 的协作链投影。真实消息链仍来自 IM,不能把这张表当成跨设备事实源。 */ export declare function getBotCollabState(db: Database.Database, scopeKey: string): CollabState | undefined; export declare function setBotCollabState(db: Database.Database, state: CollabState): void; export declare function deleteBotCollabState(db: Database.Database, scopeKey: string): void; export declare function loadPersistedBotBackend(dbPath: string, botName: string): AgentBackendType | undefined; export declare function loadPersistedBotRuntimeState(dbPath: string, botName: string): BotRuntimeState | undefined; export declare function recordRuntimeEvent(db: Database.Database, input: RuntimeEventInput): number; export declare function getRecentRuntimeEvents(db: Database.Database, query?: RuntimeEventQuery): RuntimeEventRow[]; /** 判断一个入站消息是否已经进入过本 Bot 的 Agent 回合。 */ export declare function hasRuntimeEventForMessage(db: Database.Database, query: { botId: string; chatId: string; threadId?: string; messageId: number; }): boolean; export interface RestartFailedRunInfo { botId: string; chatId: string; threadId?: string; runId: string; messageIds: number[]; previousElapsedMs?: number; } export declare function markUnfinishedRuntimeRunsFailedByRestart(db: Database.Database, botId: string, onMarked?: (run: RestartFailedRunInfo) => void): number; /** * 本地用户表里的 Bot 身份合并结果。 * * `promoted` 表示没有真实身份行时,把一个旧占位行直接改成真实 platform_id; * `mergedUserIds` 则是被合并并删除的重复行。 */ export interface BotIdentityReconciliation { canonicalUserId?: string; promoted: boolean; mergedUserIds: string[]; migratedReferenceCount: number; } /** * 把当前 Bot 的真实平台身份与历史占位身份合并。 * * 这不是一次性脚本:每次拿到真实 open_id 都会调用,重复执行不会产生变化。 * 旧 ID 必须由启动装配层明确传入,避免按显示名或模糊匹配误合并真实用户。 */ export declare function reconcileBotIdentity(db: Database.Database, platform: string, realPlatformId: string, legacyPlatformIds?: readonly string[]): BotIdentityReconciliation; /** 确保用户存在,返回内部 ID。事务保护防止并发 ID 冲突 */ export declare function ensureUser(db: Database.Database, platform: string, platformId: string, name?: string, nameSource?: string): string; /** 将用户标为应用机器人。只升不降。 */ export declare function setUserIsBot(db: Database.Database, userId: string): void; /** 按平台 ID 查本地用户身份。不存在则 undefined。 */ export declare function getUserIdentityByPlatformId(db: Database.Database, platform: string, platformId: string): { id: string; isBot: boolean; } | undefined; export declare function getUserIsBot(db: Database.Database, userId: string): boolean; /** 本群见过的 Bot:自己 + 曾在本群发过言且 is_bot=1 的用户。 */ export declare function listChatBots(db: Database.Database, chatId: string, selfUserId?: string | null): Array<{ id: string; name: string | null; }>; /** Update user name with source priority check */ export declare function updateUserName(db: Database.Database, userId: string, name: string, nameSource: string): void; /** Format short label from id + name: "U3(张三)" or "U3" */ export declare function formatShortLabel(id: string, name: string | null | undefined): string; /** * 统一的 sender 显示名称入口,输出 "U2(Zen)" 格式(不带方括号)。 * 所有 agent-facing 的消息格式化都应走这个函数,保证一致性。 */ export declare function formatSenderLabel(senderId: string | null, senderName: string | null, role: string): string; /** Get user short label: "U3(张三)" or "U3" */ export declare function getUserShortLabel(db: Database.Database, userId: string): string; /** Get user short label by platform ID */ export declare function getUserShortLabelByPlatformId(db: Database.Database, platform: string, platformId: string): string; /** Get chat short label, e.g. "C1(U1(Zen))" for p2p or "C2(GroupName)" for group */ export declare function getChatShortLabel(db: Database.Database, chatId: string): string; /** 确保会话存在,返回内部 ID。事务保护防止并发 ID 冲突 */ export declare function ensureChat(db: Database.Database, platform: string, platformId: string, type: "p2p" | "group", name?: string, userId?: string): string; /** Update chat name */ export declare function updateChatName(db: Database.Database, chatId: string, name: string): void; export interface StoredChatMetadata { chatMode?: string; groupMessageType?: string; fetchedAt?: number; } export declare function getChatMetadata(db: Database.Database, chatId: string): StoredChatMetadata | undefined; export declare function updateChatMetadata(db: Database.Database, chatId: string, metadata: StoredChatMetadata): void; /** 存储消息,返回内部消息 ID。消息 + FTS 索引在同一个事务中 */ export declare function storeMessage(db: Database.Database, msg: { chatId: string; senderId: string; sessionId?: string; role: string; contentText?: string; contentType?: string; replyTo?: number; platform: string; platformMsgId?: string; threadId?: string; platformTs?: string; platformRaw?: string; agentSeen?: boolean; createdAt?: string; }): number; export type ChatHistoryCursor = { syncTs: number | null; fetchedAt: number | null; }; export declare function getChatHistoryCursor(db: Database.Database, chatId: string): ChatHistoryCursor; export declare function setChatHistoryCursor(db: Database.Database, chatId: string, cursor: { syncTs?: number | null; fetchedAt?: number | null; }): void; export declare function getThreadHistoryCursor(db: Database.Database, chatId: string, threadId: string): ChatHistoryCursor; export declare function setThreadHistoryCursor(db: Database.Database, chatId: string, threadId: string, cursor: { syncTs?: number | null; fetchedAt?: number | null; }): void; export declare function markMessagesAgentSeen(db: Database.Database, ids: number[]): void; /** Get message content by platform message ID (for reply context) */ export declare function getMessageByPlatformId(db: Database.Database, platform: string, platformMsgId: string): { id: number; contentText: string | null; contentType: string | null; senderId: string; threadId: string | null; } | undefined; /** Update content_text for an existing message (e.g., after fetching reply context from API) */ export declare function updateMessageContent(db: Database.Database, id: number, contentText: string): void; /** Update platform_msg_id for an existing message (e.g., after bot sends and gets platform ID back) */ export declare function updateMessagePlatformId(db: Database.Database, id: number, platformMsgId: string): void; export type AdminRole = "none" | "admin" | "owner"; /** Set a user's admin role (persistent) */ export declare function setUserAdminRole(db: Database.Database, userId: string, role: AdminRole): void; /** Get a user's admin role */ export declare function getUserAdminRole(db: Database.Database, userId: string): AdminRole; /** Get all admin/owner user IDs from DB */ export declare function getAdminUserIds(db: Database.Database): Array<{ id: string; role: AdminRole; }>; export declare function hasUpdateNotification(db: Database.Database, botName: string, version: string): boolean; export declare function recordUpdateNotification(db: Database.Database, botName: string, version: string): void;