import { type SubstituteModeConfig, type SubstituteTarget } from '../bot-registry.js'; import { normalizeSubstituteMode } from './substitute-mode-normalize.js'; export { normalizeSubstituteMode }; export declare function getBotSubstituteMode(larkAppId: string): SubstituteModeConfig | undefined; export declare function updateBotSubstituteMode(larkAppId: string, raw: unknown): Promise<{ ok: true; substituteMode: SubstituteModeConfig | null; } | { ok: false; reason: string; }>; /** A single line's resolution outcome, surfaced back to the dashboard so the UI * can render ✓ name / ✗ input chips. */ export interface SubstituteTargetResolution { /** What the user typed (email / ou_ / on_ / u_ — trimmed). */ input: string; ok: boolean; openId?: string; name?: string; avatarUrl?: string; /** Machine-readable failure reason when ok=false. */ reason?: 'cross_app_open_id' | 'not_visible' | 'resolve_failed' | 'unresolvable'; } /** Injected Lark resolvers (real impls live in `im/lark/client`; tests mock). */ export interface SubstituteResolveDeps { /** Resolve a mixed list of `ou_*` / `on_*` / email strings → open_ids, with a * `raw → open_id` map (matches `resolveAllowedUsersWithMap`). `errored` * reports a transient failure during resolution (real impl swallows API * errors internally, so a thrown rejection alone can't signal this). */ resolveRaw: (larkAppId: string, raw: string[]) => Promise<{ resolved: string[]; map: Map; errored?: boolean; }>; /** open_id → profile lookup with per-cause definitive/transient distinction * (matches `getUserProfileStrict`): 'cross_app' = belongs to another app; * 'not_visible' = outside this app's contact visibility scope; 'invalid_id' * = no such user / malformed; 'error' = transient, retry may succeed. */ getProfile: (larkAppId: string, openId: string) => Promise<{ status: 'ok'; profile: { name: string; avatarUrl?: string; }; } | { status: 'cross_app'; } | { status: 'not_visible'; } | { status: 'invalid_id'; } | { status: 'error'; }>; } /** * Resolve dashboard-submitted targets into runtime-matchable ones: every * email / union_id gets turned into an app-scoped open_id (bounded by the bot's * 通讯录可见范围) and every resolved person gets a fresh display name. Entries that * can't be resolved are dropped from the stored targets but reported back with * `ok:false` so the UI can flag them. * * A tenant `userId` (no openId) can't be resolved to a name here, so it is * passed through untouched (rare hand-authored / back-compat path). */ export declare function resolveSubstituteTargets(larkAppId: string, rawTargets: unknown, deps: SubstituteResolveDeps): Promise<{ targets: SubstituteTarget[]; resolution: SubstituteTargetResolution[]; }>; //# sourceMappingURL=substitute-mode-store.d.ts.map