import { type BotDefaultOncall, type OncallChat } from '../bot-registry.js';
/**
 * Upsert an oncall binding. Returns whether it was newly created.
 */
export declare function bindOncall(larkAppId: string, chatId: string, workingDir: string): Promise<{
    ok: true;
    entry: OncallChat;
    created: boolean;
} | {
    ok: false;
    reason: string;
}>;
/**
 * Unbind oncall for `chatId` and ALWAYS write a tombstone into
 * `defaultOncallAutoboundChats`. The tombstone protects against the case
 * where a user manually fiddled with a chat (bound then unbound, or just
 * unbound) and we then mis-classify it as "new" on the next observation
 * and re-auto-bind. Treating unbind as "default's one shot is spent" is
 * symmetric with auto-bind already adding to the same list.
 *
 * Idempotent: never errors on "not bound". `wasBound` reports whether an
 * existing binding was actually removed so callers can phrase UI text
 * accordingly (the Lark `/oncall unbind` command still wants to say "未绑定"
 * vs "已解绑").
 */
export declare function unbindOncall(larkAppId: string, chatId: string): Promise<{
    ok: true;
    wasBound: boolean;
} | {
    ok: false;
    reason: string;
}>;
export declare function getOncallStatus(larkAppId: string, chatId: string): OncallChat | undefined;
/** Read the current defaultOncall config + autobound list for a bot. Used by
 *  the dashboard GET route and by the daemon's auto-bind judge. Sync because
 *  it only reads the in-memory snapshot — file-level consistency comes from
 *  the daemon never racing with itself on reads. */
export declare function getBotDefaultOncall(larkAppId: string): {
    defaultOncall: BotDefaultOncall | undefined;
    autoboundChats: string[];
};
/**
 * Persist a defaultOncall change for the given bot. The dashboard PUT route
 * is the only authorized caller — `since` is server-side authoritative so the
 * frontend can't backdate the cut-off and accidentally include existing chats.
 *
 * `since` is stamped on every enabled save, not just the first transition.
 * This matches the dashboard copy/requirement and prevents a later workingDir
 * edit from reaching chats that were first observed before that edit.
 *
 * When disabled with an empty `workingDir`, the prior workingDir is preserved
 * so the UI can round-trip (toggle off → toggle back on) without forcing the
 * user to retype the path. Disable with a non-empty workingDir overwrites.
 */
export declare function updateBotDefaultOncall(larkAppId: string, patch: {
    enabled: boolean;
    workingDir: string;
}): Promise<{
    ok: true;
    defaultOncall: BotDefaultOncall;
} | {
    ok: false;
    reason: string;
}>;
/**
 * Auto-bind a chat as part of the defaultOncall flow. Atomically:
 *   1. RE-CHECK tombstone + existing binding against the freshest on-disk
 *      snapshot. The daemon's fast-path tombstone check is informational —
 *      if a concurrent `unbindOncall` wrote a tombstone between then and
 *      now, the lock-internal view sees it and we skip.
 *   2. Upsert the oncallChats entry (same shape as manual bindOncall).
 *   3. Append chatId to defaultOncallAutoboundChats (idempotent).
 *
 * Returns `skipped: 'tombstoned'` when the lock-internal tombstone check
 * trips, `skipped: 'already_bound'` when another writer (manual bind by
 * the user, or a sibling daemon) bound the chat between the fast-path read
 * and the lock acquisition. Neither is an error.
 */
export declare function autoBindOncallFromDefault(larkAppId: string, chatId: string, workingDir: string): Promise<{
    ok: true;
    entry: OncallChat;
    created: boolean;
    skipped?: undefined;
} | {
    ok: true;
    skipped: 'tombstoned' | 'already_bound';
    entry?: undefined;
    created?: undefined;
} | {
    ok: false;
    reason: string;
}>;
/**
 * 前置 auto-bind：dispatcher 在权限判断前调用，保证 oncall 群的首条 @bot 消息
 * 不被误判为"无权限"弹授权申请卡。
 *
 * 做了与 daemon 侧一致的快速短路：非群聊 / defaultOncall 未开 / 已在 tombstone 列表
 * / chat 已有显式 oncall 绑定 → 立刻 return；否则调 autoBindOncallFromDefault
 * （内部会在锁内做权威二次校验）。idempotent，daemon spawn 路径二次调用安全。
 */
export declare function ensureDefaultOncallBound(larkAppId: string, chatId: string, chatType: 'group' | 'p2p'): Promise<OncallChat | undefined>;
export declare function _readRawConfigSyncForTesting(path: string): any[];
//# sourceMappingURL=oncall-store.d.ts.map