import type { CliRuntimeConfig as SharedCliRuntimeConfig } from '../../adapters/cli/runtime.js'; import type { FeedbackPolicyLayer } from '../../services/feedback-policy-resolver.js'; export type CliOption = { id: string; label: string; gateway?: 'ttadk'; acceptsModel?: boolean; available?: boolean; command?: string; availabilityReason?: string; /** 静态模型候选(后端精选列表;不支持模型的 CLI 为 [])。live 探测结果走 /api/cli-options/models。 */ modelChoices?: readonly string[]; }; export type CliOptionsState = { options: CliOption[]; ttadkModelDefault: string; ttadkModelSuggestions: string[]; }; /** Keep the browser payload contract tied to the daemon's canonical schema. */ export type CliRuntimeConfig = SharedCliRuntimeConfig; export type CliRuntimeUpdateProvider = NonNullable['provider']; export type BotSubstituteTarget = { openId?: string; userId?: string; unionId?: string; email?: string; name?: string; avatarUrl?: string; }; export type BotSubstituteMode = { enabled: boolean; targets: BotSubstituteTarget[]; disclosure: 'prefix' | 'none'; chats?: string[]; excludedChats?: string[]; replyMode?: 'thread' | 'quote'; disableControlCard?: boolean; /** 话题群支持(缺省 true;显式 false 关)。 */ topicGroups?: boolean; /** 话题里已有本 bot 活跃会话时是否仍触发替身(缺省 true)。 */ topicActiveSessionTrigger?: boolean; }; export type BotDefaultsRow = { larkAppId: string; botName?: string; cliId?: string; /** 租户品牌,决定飞书后台深链的 host(feishu.cn vs larksuite.com)。 * 缺省(旧 payload / 未注册)→ larkConsoleUrl 内 normalizeBrand 兜底 feishu。 */ brand?: string; /** Absent/null is the built-in runtime. Older dashboard payloads omit it. */ cliRuntime?: CliRuntimeConfig | null; /** Legacy path-only executable override, returned only by private Bot Defaults APIs. */ cliPathOverride?: string | null; wrapperCli?: string | null; model?: string; reasoningEffort?: 'low' | 'medium' | 'high' | 'xhigh' | 'max' | 'ultra'; /** dsh runner turn timeout (ms); rendered as a dsh-only field. */ turnTimeoutMs?: number; /** dsh runtime variant: 'official' (JSON-RPC runner) or 'tui' (dsh-tui PTY). */ dshRuntime?: 'official' | 'tui' | null; agentSelectionKey?: string; defaultOncall?: { enabled?: boolean; workingDir?: string; since?: number; }; defaultWorkingDir?: string | null; defaultWorkingDirAutoWorktree?: boolean; autoboundChatCount?: number; brandLabel?: string | null; sandbox?: boolean; /** Three-tier sandbox path whitelist (highest-precedence FsPolicy layer). * null/absent = none configured (pure deny-by-default baseline). */ sandboxPaths?: { readWrite: string[]; readOnly: string[]; deny: string[]; } | null; /** Whether the unified file sandbox ALSO applies cross-bot read isolation for * this bot's sessions — true when the CLI (claude/codex) + platform (macOS/Linux) * + no wrapper can enforce it. Drives the capability label under the toggle. */ readIsolationSupported?: boolean; backendType?: string | null; usageDisplay?: 'streaming' | 'footer' | 'off'; usageSupported?: boolean; disableStreamingCard?: boolean; silentTurnReactions?: boolean; codexAppCleanInput?: boolean; writableTerminalLinkInCard?: boolean; privateCard?: boolean; overloadAlert?: boolean; botToBotSameDir?: boolean; summaryRange?: { limit?: number; sinceHours?: number; }; summaryMemory?: boolean; summaryMemoryPath?: string; p2pMode?: string; /** #794: per-turn 上下文注入方式。'auto' = 支持的 CLI 走 hook 注入;缺省/'off' = 内联。 */ envelopeInjection?: 'auto' | 'off' | null; regularGroupReplyMode?: string; regularGroupMentionMode?: string; substituteMode?: BotSubstituteMode | null; feedback?: FeedbackPolicyLayer | null; docSubscribeDefaultMode?: string; maxLiveWorkers?: number | null; logicalSessionCount?: number; residentSessionCount?: number; dormantSessionCount?: number; sessionOwnerReminder?: { enabled: boolean; intervalMinutes: number; text: string; states: Array<'idle' | 'dormant' | 'pending_repo' | 'tui_prompt' | 'agent_attention' | 'limited'>; } | null; startupCommands?: string; customPassthroughCommands?: string; canTalkDaemonCommands?: string; launchShell?: string; env?: string; riff?: Record | null; autoStartOnGroupJoin?: boolean; autoStartOnGroupJoinPrompt?: string; autoStartOnNewTopic?: boolean; autoGrantRequestCards?: boolean; restrictGrantCommands?: boolean; p2pOpen?: boolean; grantDefaultDurationMs?: number | null; messageQuotaDefaultLimit?: number | null; skillInjectionSupport?: 'dynamic' | 'global' | 'none' | string; skillInjection?: 'global' | 'prompt' | 'off' | null | string; skillInjectionDefault?: 'global' | 'prompt' | 'off' | string; displayName?: string | null; larkBotName?: string | null; teamRole?: string; teamRoleLoading?: boolean; error?: string; }; export type LoadBotsResult = { bots: BotDefaultsRow[]; error: string | null; }; export declare const fallbackCliOptions: CliOption[]; export declare const fallbackCliOptionsState: CliOptionsState; export declare function displayCliId(bot: Pick | null | undefined, sessionFallback: string): string; /** Fallback for old /api/bots payloads: infer from the bot's recent sessions. */ export declare function cliIdOf(appId: string): string; export declare function agentSelectionKey(bot: BotDefaultsRow, sessionFallback: string): string; export declare function selectedCliOption(options: CliOption[], key: string): CliOption | undefined; export declare function modelSuggestionsForOption(opt: CliOption | undefined, cliState: CliOptionsState): string[]; /** * 合并模型候选:detected(后端已合并静态+live 去重)优先;detected 缺失时回退 static。 * 两份列表再做一次去重保序,防御后端合并遗漏。纯函数,供单测。 */ export declare function mergeModelCandidates(staticChoices: readonly string[], detected: readonly string[] | null | undefined): string[]; /** * 按需探测某个 CLI 当前可用的模型列表(静态精选 + live 探测合并去重)。 * fail-soft:任何错误(网络/404/400/形状异常)都返回 null,调用方回退静态候选。 */ export declare function fetchDetectedModels(key: string): Promise<{ models: string[]; source: 'live' | 'static'; } | null>; /** * Latest-wins guard for overlapping async refreshes. The Bot 配置 page fires an * initial refresh on mount and another on every `bots.changed` SSE event; these * can overlap, and a slow earlier `/api/bots` response arriving *after* a newer * one ("后发先回") would otherwise clobber the fresher roster and re-hide a * just-added bot. Each call bumps a monotonic counter and hands back a `commit` * predicate that is only true while this call is still the newest — the caller * gates BOTH its state write and its `loading=false` on it. Kept as a tiny * pure factory so the race is unit-testable without a DOM. */ export declare function createRefreshGate(): { begin(): { commit(): boolean; }; }; export declare function fetchBotDefaults(): Promise; export type SubstituteTargetResolution = { input?: string; ok?: boolean; openId?: string; name?: string; avatarUrl?: string; reason?: 'cross_app_open_id' | 'not_visible' | 'resolve_failed' | 'unresolvable'; }; export declare function resolveSubstituteTarget(larkAppId: string, target: BotSubstituteTarget): Promise<{ ok: false; error: string; } | { ok: true; resolution: SubstituteTargetResolution; }>; export declare function fetchCliOptions(): Promise; export declare function fmtSince(since: number): string; //# sourceMappingURL=bot-defaults.d.ts.map