/**
 * `/config` 远程编辑 bot 运营字段。与 oncall-store / grant-prefs-store / brand-store
 * 同款：跨进程文件锁 + bots.json 原子写（rmwBotEntry），外加内存 registry 同步——
 * 因此 **无需重启 daemon**：读取实时配置的字段立即生效，spawn 时才读取的字段
 * （model / cliId / disableCliBypass / defaultWorkingDir）下一个新会话生效。
 *
 * 刻意只覆盖「运营字段」。secret（larkAppSecret / voice 凭证）绝不经此路径修改——
 * 聊天通道会被 IM 侧记录，引导新 bot / 换密钥仍走本机 `botmux setup`。授权额度
 * （grants / quota）由既有 `/grant` 负责，不在此重复。
 */
import type { BotConfig } from '../bot-registry.js';
/**
 * 生效时机：
 *   • immediate     — 运行时读取实时 `bot.config`，热更新后下一条消息/事件即生效。
 *   • next-session  — spawn CLI 时才读取，当前运行中的会话需 `/restart` 重启才换新值；
 *                     新会话直接用新值。
 */
export type ConfigEffect = 'immediate' | 'next-session';
export type ConfigFieldKind = 'string' | 'boolean' | 'enum' | 'cli' | 'dir' | 'allowedUsers';
export interface ConfigFieldSpec {
    /** 用户面命令里用的字段名（大小写不敏感匹配，见 {@link findConfigField}）。 */
    key: string;
    /** bots.json / 内存 BotConfig 上的实际字段。 */
    configKey: keyof BotConfig;
    kind: ConfigFieldKind;
    effect: ConfigEffect;
    /** 是否支持 `/config unset <field>`（清回默认）。boolean 字段用 `set off` 即可，无需 unset。 */
    clearable: boolean;
    /** kind==='enum' 时的合法取值（已小写）。 */
    enumValues?: readonly string[];
    /** 一句话说明，进 `/config help` / `/config get`。 */
    hint: string;
}
/**
 * Phase 1 可编辑的运营字段。**不含** allowedUsers 之外的权限字段、secret、brand
 * （绑定租户、需重启重建 client）、name（pm2 进程名，启动期绑定）。allowedUsers
 * 在此登记但走 {@link setBotAllowedUsers} 的专用异步路径（重解析 + 防自锁）。
 */
export declare const CONFIG_FIELDS: readonly ConfigFieldSpec[];
/** 大小写不敏感地按 key 找字段 spec。 */
export declare function findConfigField(key: string): ConfigFieldSpec | undefined;
/** 可设置字段名列表（用于报错提示 / help）。 */
export declare function settableFieldKeys(): string[];
/** 把 on/off 类输入解析成布尔，无法识别 → undefined。 */
export declare function parseBooleanValue(raw: string): boolean | undefined;
export interface ConfigSnapshotRow {
    key: string;
    value: string;
    effect: ConfigEffect;
}
/** 当前可编辑字段的快照（供 `/config get`）。不含 secret。 */
export declare function getConfigSnapshot(larkAppId: string): {
    ok: true;
    rows: ConfigSnapshotRow[];
    info: {
        cliId: string;
        brand: string;
        resolvedAdmins: number;
        workingDirs: string[];
    };
} | {
    ok: false;
};
export type ApplyFieldResult = {
    ok: true;
    oldText: string;
    newText: string;
    effect: ConfigEffect;
} | {
    ok: false;
    reason: 'bot_not_registered' | 'bot_not_in_config' | string;
};
/**
 * 写入并热更新一个**已解析**的字段值（string / boolean / null=清除）。
 * 调用方负责按 kind 校验后再传值；本函数只负责落盘 + 同步内存。
 * 不处理 allowedUsers（异步，见 {@link setBotAllowedUsers}）。
 */
export declare function applyConfigField(larkAppId: string, spec: ConfigFieldSpec, value: string | boolean | null): Promise<ApplyFieldResult>;
export type SetAllowedUsersResult = {
    ok: true;
    raw: string[];
    resolved: string[];
} | {
    ok: false;
    reason: 'bot_not_registered' | 'bot_not_in_config' | 'self_lockout' | 'empty_resolved' | string;
};
/**
 * 改 allowedUsers（管理员名单）。这是动信任根的敏感操作，与普通字段分开：
 *   1. 用 bot 凭证把邮箱/on_ 解析成 open_id（与启动期同一路径）。
 *   2. **防自锁**：解析后名单必须仍含发起人的 open_id，否则拒绝——避免把自己踢出管理员。
 *   3. 解析后非空才写。
 *   4. 落盘原始条目（邮箱/on_/ou_，与 setup 一致），并同步内存 resolvedAllowedUsers /
 *      rawAllowedUserResolution（与 daemon 启动期赋值同口径），无需重启。
 *
 * confirm 二次确认由调用方（command-handler）处理，本函数只做校验 + 落盘。
 */
export declare function setBotAllowedUsers(larkAppId: string, rawEntries: string[], senderOpenId: string | undefined): Promise<SetAllowedUsersResult>;
export type CoerceResult = {
    ok: true;
    value: string | boolean;
} | {
    ok: false;
    reason: 'invalid_bool' | 'invalid_enum' | 'invalid_cli' | 'invalid_dir' | 'empty';
};
/**
 * 把一个**原始**字段值（来自卡片下拉/输入或别处）按字段 kind 解析校验成可落盘的
 * string|boolean。dir 在此做存在性检查（无 locale，返回结构化 reason，调用方再本地化）。
 * allowedUsers 不走这里（异步，见 {@link setBotAllowedUsers}）。
 */
export declare function coerceConfigValue(spec: ConfigFieldSpec, raw: unknown): CoerceResult;
/**
 * 渲染交互配置卡片所需的纯数据视图。card-builder 只吃这个（不反向 import store），
 * 避免循环依赖。`modelChoices` 由调用方按 cliId 解析后传入（command-handler /
 * card-handler 已 import CLI 适配器），缺省空数组 → 不渲染 model 下拉。
 */
export interface ConfigCardData {
    larkAppId: string;
    botName: string;
    cliId: string;
    cliOptions: Array<{
        id: string;
        label: string;
    }>;
    model: string | null;
    modelChoices: string[];
    lang: string | null;
    /** 私聊单聊模式 p2pMode（'chat' | 'thread'）；null = 未设（默认 thread）。 */
    p2pMode: string | null;
    brandLabel: string | null;
    defaultWorkingDir: string | null;
    /** 入群主动开工首轮 prompt（autoStartOnGroupJoinPrompt）。 */
    autoStartPrompt: string | null;
    /** team 级默认角色文本（不在 bots.json，存独立角色文件）。 */
    teamRole: string | null;
    /** messageQuota.defaultLimit（被授权人默认消息额度）；null = 不限。 */
    quota: number | null;
    admins: number;
    booleans: Array<{
        key: string;
        on: boolean;
    }>;
}
export declare function getConfigCardData(larkAppId: string, modelChoices?: readonly string[]): ConfigCardData | null;
//# sourceMappingURL=bot-config-store.d.ts.map