/**
 * DigitalHuman — Standalone ES module for virtual character rendering and AI session management.
 *
 * Responsibilities:
 *   1. Avatar rendering: Video / Live2D / WebP with lip sync
 *   2. AI Chat Session: Full lifecycle via KeepworkSDK's aiChat.createSession()
 *   3. Voice Chat: Real-time voice via AIChatRTC SDK class
 *
 * NOT responsible for: progress bar, game scoring, quick replies,
 * history dropdown, AI toolbox sidebar, file upload UI, inner thoughts display.
 *
 * Usage:
 *   import DigitalHuman from './libs/digitalhuman';
 *   const dh = new DigitalHuman({ sdk, container: document.getElementById('avatar-root') });
 *   await dh.initAvatar(videoActions);
 *   dh.on('message', ({ partialText }) => { ... });
 *   dh.on('bracketAction', ({ actionKey }) => dh.playAction(actionKey, 3));
 *   await dh.createSession({ system_prompt: '...', llm_model: 'keepwork-flash', tools: { fileOps: { enabled: true } } });
 *   await dh.send('Hello');
 *
 * initFromConfig (one-call setup from characterManager-style config):
 *   const dh = new DigitalHuman({ sdk, container });
 *   const info = await dh.initFromConfig({
 *     system_prompt: '你是一个友好的助手',
 *     llm_model: { model: 'keepwork-flash', temperature: 0.7, reasoning: false },
 *     videoActions: { '待机': { url: '...' }, '说话': { url: '...' } },
 *     bracketAction: { enabled: true, autoplay: true, duration: 3 },
 *     textToSpeech: { enabled: true, provider: 'speechRTC', voiceType: 'zh_female_cancan_mars_bigtts' },
 *     tools: { fileOps: { enabled: true, workspace: 'ws' }, web: { enabled: true } },
 *     avatar_only: false,
 *   });
 *   // bracketAction boolean => emit-only
 *   // bracketAction object  => emit + optional autoplay
 *   // info = { session, config }
 *   // Full config (character, quick_replies, etc.) available via dh.characterConfig
 *
 * videoActions format (supports pipe-separated aliases):
 *   {
 *     '待机': { url: 'https://cdn.../model.model3.json' },
 *     'talk': { url: 'https://cdn.../talk.mp4' },
 *     '高兴|happy': { url: 'https://cdn.../happy.mp4' },
 *     '难过|sad':   { url: 'https://cdn.../sad.mp4' },
 *   }
 *   Built-in aliases (always available): you can specify either '待机' or 'idle' or '0' for the idle action,
 *     and '说话' or 'talk' or '1' for the talk action.
 *
 * playAction(actionKey, duration):
 *   dh.playAction('happy', 5);   // play for 5s then back to idle
 *   dh.playAction('talk', -1);   // play indefinitely
 *   dh.playAction(0);            // switch to idle (via alias)
 *   Repeated calls with the same key reset the timer without restarting the action.
 *
 * loadConfig (one-call setup from a config URL, JSON string, or object):
 *   // Load from a .md file (YAML frontmatter = config, body = system_prompt):
 *   await dh.loadConfig('https://example.com/character.md');
 *   // Load from a .json or .yml URL:
 *   await dh.loadConfig('https://example.com/character.json');
 *   // Load from an inline JSON string:
 *   await dh.loadConfig('{"system_prompt":"Hi","llm_model":"keepwork-flash"}');
 *   // Load from a plain object (equivalent to initFromConfig):
 *   await dh.loadConfig({ system_prompt: 'Hi', llm_model: 'keepwork-flash' });
 *
 *   Supported .md format (YAML frontmatter + markdown body as system_prompt):
 *   ---
 *   llm_model: keepwork-flash
 *   videoActions:
 *     待机:
 *       url: "https://cdn.../model.model3.json"
 *   tools:
 *     fileOps:
 *       enabled: true
 *       workspace: myWorkspace
 *   bracketAction:
 *     enabled: true
 *     autoplay: true
 *   textToSpeech:
 *     enabled: true
 *     provider: speechRTC
 *     voiceType: zh_female_cancan_mars_bigtts
 *   voiceChat:
 *     appId: "..."
 *   ---
 *   你是拉拉，一个友善的AI角色。请用简短、口语化的中文回复用户。
 */
type DHAny = any;
export default class DigitalHuman {
    [key: string]: any;
    /**
     * @param {Object} options
     * @param {Object} options.sdk - KeepworkSDK instance
     * @param {HTMLElement} [options.container] - Container element for avatar rendering
     * @param {Object} [options.config] - Initial configuration
     */
    constructor({ sdk, container, config, subtitle }?: DHAny);
    get on(): any;
    get off(): any;
    get emit(): any;
    /**
     * Register a slash command that can be intercepted by send().
     * @param {string} name - Command name (without leading /)
     * @param {Object} def
     * @param {string} def.description - Short help text
     * @param {boolean} [def.needsArg=true] - Whether the command requires an argument
     * @param {function(string, Object):void|Promise<void>} def.handler - Receives (argString, thisDigitalHuman)
     */
    registerCommand(name: DHAny, { description, needsArg, handler }: DHAny): void;
    /**
     * Unregister a slash command.
     * @param {string} name
     */
    unregisterCommand(name: DHAny): void;
    /**
     * List all registered slash commands.
     * @returns {Array<{ name: string, description: string, needsArg: boolean }>}
     */
    listCommands(): {
        name: string;
        description: any;
        needsArg: any;
    }[];
    /**
     * Try to dispatch a slash command from a user message string.
     * @param {string} text
     * @returns {{ handled: boolean, name?: string, result?: * }}
     */
    tryCommand(text: DHAny): {
        handled: boolean;
        name?: undefined;
        error?: undefined;
        result?: undefined;
    } | {
        handled: boolean;
        name: string;
        error: string;
        result?: undefined;
    } | {
        handled: boolean;
        name: string;
        result: any;
        error?: undefined;
    };
    /** @private */
    _registerBuiltinCommands(): void;
    /**
     * Create the avatar DOM elements inside the container.
     * @param {HTMLElement} [container] - Override container
     */
    _createAvatarDOM(container?: DHAny): void;
    setSubtitleConfig(config?: DHAny): any;
    getSubtitleConfig(): any;
    clearSubtitle(options?: DHAny): void;
    showSubtitle(text: DHAny, options?: DHAny): void;
    _getAudioEngine(): any;
    _bindAudioResumeTarget(target: DHAny): void;
    _clearAudioResumeBindings(): void;
    static DEFAULT_VIDEO_ACTIONS: {
        待机: {
            url: string;
        };
    };
    static BUILTIN_ALIASES: DHAny;
    /**
     * Normalize videoActions: expand pipe-separated keys into individual entries
     * and merge built-in aliases. Returns a new flat object.
     * @param {Object} raw - e.g. { '待机|idle|0': { url }, '高兴|happy': { url } }
     * @returns {Object} Normalized map keyed by every alias
     */
    _normalizeVideoActions(raw: DHAny): any;
    /**
     * Resolve an action key through aliases to its config object.
     * @param {string|number} key
     * @returns {Object|undefined} The action config { url, ... }
     */
    _resolveAction(key: DHAny): any;
    /**
     * Collect idle variant configs (idle2, idle3, …) from _videoActions.
     * These are used for random idle animations when voice mode is off.
     */
    _collectIdleVariants(): void;
    /**
     * Schedule a random idle variant to play after a debounce period.
     * Called from switchToIdle() when conditions are met:
    *   - voice chat is NOT active, or DigitalHuman is inactive
     *   - there are idle variants available
     * The main idle plays immediately; after DEEP_IDLE_DEBOUNCE_MS a random variant is picked.
     * @param {number} [delayMs] - Override debounce duration (0 for immediate, e.g. on first load)
     */
    _scheduleRandomIdle(delayMs?: DHAny): void;
    /**
     * Cancel any pending random idle scheduling.
     */
    _cancelRandomIdle(): void;
    /**
     * Pick and play a random idle variant from the pool.
     */
    _playRandomIdleVariant(): void;
    /**
     * Get all available actions as pipe-joined alias strings.
     * Each entry is a string like 'idle|待机' or '写字|记录|writing'.
     * Built-in alias keys are included for idle/talk entries.
     * idle and talk entries (if present) are returned first.
     * @returns {string[]}
     */
    getActions(): string[];
    /**
     * Resolve normalized bracket-action options from request/session/config state.
     * Boolean `true` enables event emission only; object form can also enable autoplay.
      * Supported object keys: enabled, autoplay/autoPlay, duration/playDuration.
      * Bracket scanning is always limited to the first 500 words of the text.
     * @param {Object} [options]
     * @returns {{ enabled: boolean, autoplay: boolean, duration: number }}
     */
    _getBracketActionOptions(options: DHAny): {
        enabled: boolean;
        autoplay: boolean;
        duration: number;
    };
    /**
     * Whether LLM bracket-action scanning is enabled for the current request.
     * Priority: request options -> session config -> character config -> constructor config.
     * Supported keys: bracketAction / autoBracketAction.
     * @param {Object} [options]
     * @returns {boolean}
     */
    _isBracketActionEnabled(options: DHAny): boolean;
    /**
     * Resolve summarization options from request/session/config state.
     * Priority: request options -> summarizeAgent config -> session config -> character config -> constructor config.
      *
      * These options drive all DigitalHuman-owned summarization entry points:
      * - manual `summarize()` calls
      * - post-send auto checks (`trigger: 'auto'`)
      * - idle timer checks (`trigger: 'silentTick'`)
      *
      * Startup history restore via keepHistory is intentionally excluded. Existing
      * history is loaded into the session, but summarization is not auto-triggered
      * just because restored messages already exceed the thresholds.
     *
     * Supported shapes:
     *  - `true`  => enable with defaults (maxRounds=20, maxTextLength=8000, keepRecentRounds=3)
     *  - `{ enabled: true, maxRounds, maxTextLength, keepRecentRounds, prompt, model, enableTools }`
     *  - `summarizeAgent` config: presence implies enabled=true; thresholds and mode are read from it
     *
     * @param {Object} [options]
     * @returns {{ enabled: boolean, maxRounds: number, maxTextLength: number, keepRecentRounds: number, prompt: string|undefined, model: string|undefined, enableTools: string[]|undefined, mode: string, async: boolean, silentTickInterval: number }}
     */
    _getSummarizationOptions(options?: DHAny): {
        enabled: boolean;
        maxRounds: number;
        maxTextLength: number;
        keepRecentRounds: number;
        prompt: any;
        model: any;
        enableTools: any;
        mode: any;
        async: boolean;
        silentTickInterval: number;
    };
    /**
     * Load and initialize a dedicated summarize agent from a config source.
     * Delegates to the SummarizeAgent instance for session creation and CopilotTools override.
     * @param {string|Object} source - Config URL, JSON string, or config object
     * @returns {Promise<Object>} The parsed agent config
     */
    loadSummarizeAgentConfig(source: DHAny): Promise<any>;
    /**
     * Send background context to both the text ChatSession and the voice RTC session.
     * In text mode, context is queued via ChatSession.sendContext() and flushed
     * automatically on the next ChatSession.send() or voice-to-text mirror commit.
     * In voice mode, context is also sent immediately via the RTC binary channel.
     *
     * When `insertToHistory` is true, a fake user/assistant pair is also written
     * into the session message list and persisted to the keepHistory files.
     * The user message is the context text and the assistant reply is "(OK)".
     * This pair is excluded from dialog summarization.
     * @param {string} text - Context text to inject
     * @param {Object} [options]
     * @param {boolean} [options.insertToHistory=false] - Also persist as a Q/A pair in history
     */
    sendContext(text: DHAny, options?: DHAny): void;
    /**
     * Handle an external send message. Optionally interrupts current speech/response,
     * then sends the message through the normal send() flow.
     * @private
     * @param {Object} msg - { type: 'dh:send', text: string, interrupt?: boolean, options?: object }
     */
    _handleExternalSend(msg: DHAny): Promise<void>;
    /**
     * Handle an external context message. Buffers context and optionally starts
     * a debounce timer. Default debounce is Infinity (context only sent with
     * next user message). Finite debounce auto-sends with "(continue)" after
     * the specified milliseconds.
     * @private
     * @param {Object} msg - { type: 'dh:context', text: string, debounce?: number }
     */
    _handleExternalContext(msg: DHAny): void;
    /**
     * Auto-flush buffered context by sending a "(continue)" user message.
     * @private
     */
    _autoFlushExternalContext(): Promise<void>;
    /** Flush buffered context (cancel debounce timer, context already queued). @private */
    _flushExternalContext(): void;
    /** @private */
    _normalizeVoiceHeartbeatConfig(value: DHAny, fallback?: DHAny): any;
    /** @private */
    _resolveVoiceHeartbeatConfig(preset?: DHAny, options?: DHAny): any;
    /** @private */
    _setupVoiceHeartbeat(config: DHAny): void;
    /** @private */
    _clearVoiceHeartbeat(options?: DHAny): void;
    /** @private */
    _isVoiceHeartbeatAgentIdle(): boolean;
    /** @private */
    _canRunVoiceHeartbeat(config?: any): boolean;
    /** @private */
    _scheduleVoiceHeartbeat(): void;
    /** @private */
    _scheduleVoiceHeartbeatAfter(delayMs: DHAny): void;
    /** @private */
    _resetVoiceHeartbeatActivity(): void;
    /** @private */
    _formatVoiceHeartbeatText(rawText: DHAny, meta: DHAny): string;
    /**
     * Trigger the voice heartbeat path immediately from app code.
     * This is useful when the app already knows the current business state and
     * wants to avoid asking the LLM to inspect the page with read_app.
     * @param {string|Object} input - Explicit heartbeat text, or { text, reason, context, data }.
     * @param {Object} [options]
     * @returns {Promise<Object>}
     */
    triggerVoiceHeartbeat(input?: DHAny, options?: DHAny): Promise<any>;
    /** @private */
    _sendVoiceHeartbeat({ trigger, rawText, meta, options }?: DHAny): Promise<any>;
    /** @private */
    _onVoiceHeartbeatTimeout(): Promise<void>;
    /** @private */
    _emitActiveState(reason?: string): void;
    /** @private */
    _clearInactiveVoiceStopTimer(): void;
    /** @private */
    _clearVoiceIdleTimer(): void;
    /** @private */
    _resetVoiceIdleTimer(): void;
    /** @private */
    _normalizeVoiceLifecycleConfig(value: DHAny, fallback?: DHAny): any;
    /** @private */
    _resolveVoiceLifecycleConfig(preset?: DHAny, options?: DHAny): any;
    /** @private */
    _isDocumentHidden(): boolean;
    /** @private */
    _emitVoiceLifecycleState(state: DHAny, extra?: DHAny): void;
    /** @private */
    _setupVoiceLifecycleHandlers(config: DHAny): void;
    /** @private */
    _clearVoiceLifecycleHandlers(): void;
    /** @private */
    _enterVoiceLifecycleStandby(reason?: string): Promise<void>;
    /** @private */
    _resumeVoiceLifecycleFromStandby(reason?: string): Promise<void>;
    /** @private */
    _stopVoiceConnectionForInactive(reason?: string): Promise<void>;
    /** @private */
    _scheduleInactiveVoiceStop(options?: DHAny): void;
    /** @private */
    _sendCurrentPageRouterWakeupIfNeeded(): Promise<boolean>;
    /** @private */
    _switchToInactiveIdle(): void;
    /**
     * Set whether the digital human is actively listening/speaking.
     * This does not switch text/voice mode. Starting voice mode activates it;
     * stopping voice mode makes it inactive.
     * @param {boolean} active
     * @param {Object} [options]
     * @returns {Promise<Object>}
     */
    setActive(active?: boolean, options?: DHAny): Promise<{
        ok: boolean;
        active: any;
        changed: boolean;
    }>;
    /** @private */
    _startPageRouterHeartbeat(page: DHAny, routerEntry: DHAny): void;
    /**
     * Immediately send heartbeat text. If text is omitted, use the active
     * page router heartbeatText; if that is unavailable, send "[heartbeat]".
     * @param {string} [text] - Explicit heartbeat text to send.
    * @param {Object} [options] - send() options. Defaults keep heartbeat out of history and skips empty runCode output.
     * @returns {Promise<Object>} Result metadata plus the send() response.
     */
    sendHeartbeat(text: DHAny, options?: DHAny): Promise<{
        ok: boolean;
        sent: boolean;
        skipped: boolean;
        reason: string;
        page: any;
        text?: undefined;
        data?: undefined;
    } | {
        ok: boolean;
        sent: boolean;
        page: string | null;
        text: any;
        data: any;
        skipped?: undefined;
        reason?: undefined;
    }>;
    /**
     * Handle an AppPageOpened message. Looks up the page in _pageRouters,
     * restarts the agent / sends wakeup text if configured, and manages
     * page-scoped heartbeat text.
     * @private
     * @param {Object} msg - { type: 'dh:app-page-opened', page: string }
     */
    _handleAppPageOpened(msg: DHAny): Promise<void>;
    /**
     * Trigger conversation summarization.
     * This is the single DigitalHuman entry point for both manual and automatic
     * summarization requests. Automatic callers can set `trigger` and
     * `onlyWhenNeeded` to reuse the same queueing and threshold checks as manual
     * summaries.
     * Routes to the dedicated SummarizeAgent if configured, otherwise falls back
     * to the built-in SummarizeTool. Returns immediately. Only one summarization
     * runs at a time; subsequent calls are queued and merged so the latest
     * options win.
      *
      * Behavior summary:
      * - fire-and-forget: this method does not return the summary result
      * - result delivery: listen for the `summarized` event
      * - manual trigger: call `summarize()` with no gating flags
      * - automatic trigger: call with `onlyWhenNeeded: true`; threshold checks are
      *   evaluated against the current session message history
      * - duplicate suppression: automatic requests in the same threshold bucket are
      *   skipped until the conversation grows into a new bucket
      * - queue merging: if a run is already active, a later request replaces the
      *   pending request so only the latest queued options are kept
      * - startup behavior: restoring keepHistory content does not call summarize()
      *   automatically
      *
     * Listen for the 'summarized' event to receive the result.
     * @param {Object} [options]
     * @param {number} [options.keepRecentRounds=3] - Number of recent user+assistant pairs to preserve
     * @param {string} [options.mode] - 'replace' (compress in place) or 'append' (return summary only)
      * @param {string} [options.trigger='manual'] - Event trigger label such as 'manual', 'auto', or 'silentTick'
     * @param {boolean} [options.onlyWhenNeeded=false] - Gate execution by maxRounds/maxTextLength thresholds
     */
    summarize(options?: DHAny): void;
    /**
     * Collect summarization metrics from the live text session.
     * System messages are excluded. `roundCount` is based on user messages only.
     * `totalTextLength` counts string message content currently stored in the
     * session and is used together with `maxTextLength` for auto-trigger gating.
     * @returns {{ roundCount: number, totalTextLength: number }|null}
     */
    _collectSummarizeMetrics(): {
        roundCount: number;
        totalTextLength: number;
    } | null;
    /**
     * Build a stable auto-trigger signature for the current threshold bucket.
     * Automatic summarization requests are skipped while the session remains in
     * the same bucket, which prevents repeated summaries after every send or idle
     * tick without new conversation growth.
     * @param {{ roundCount: number, totalTextLength: number }|null} metrics
     * @param {Object} [options]
     * @returns {string|null}
     */
    _getSummarizeAutoTriggerSignature(metrics: DHAny, options?: DHAny): string | null;
    /**
     * Decide whether a threshold-gated summarization request should run.
     *
     * This is only used when callers pass `onlyWhenNeeded: true`. Manual calls
     * bypass this method and always attempt to summarize.
     *
     * Returns false when:
     * - summarization is disabled by resolved config
     * - there is no active AI session/message list
     * - both `maxRounds` and `maxTextLength` thresholds are still below target
     * - the current conversation is still in the same auto-trigger bucket as the
     *   last completed/attempted gated request
     *
     * Returns true once the conversation crosses into a new threshold bucket.
     * @param {Object} [options]
     * @returns {boolean}
     */
    _shouldRunSummarize(options?: DHAny): boolean;
    /**
     * Start the DigitalHuman-owned silent-tick summarization timer.
     *
     * The timer does not summarize immediately on each tick. Instead it waits for
     * `silentTickInterval` seconds of inactivity, then calls `summarize()` with
     * `trigger: 'silentTick'` and `onlyWhenNeeded: true` so the same threshold
     * gating and queue semantics are reused.
     */
    _startSummarizeTimer(): void;
    /** Stop the DigitalHuman-owned silent-tick summarization timer. */
    _stopSummarizeTimer(): void;
    /** Record the latest user/assistant activity time for silent-tick checks. */
    _resetSummarizeActivity(): void;
    /**
     * Execute one summarization request and then drain any merged pending request.
     *
     * Result handling:
     * - emits `summarized` on success or error
     * - preserves the caller-provided `trigger` in the event payload
     * - forwards the returned summary into `sendContext()` when available so later
     *   turns can reuse the compressed context
     * - updates keepHistory cutoff state when the summarizer reports
     *   `summarizeBeginTime`
     *
     * This method is internal. External callers should always use `summarize()`.
     * @private
     */
    _runSummarize(options: DHAny): Promise<void>;
    /**
     * Resolve non-RTC text-to-speech options from request/session/config state.
     * Supported shapes:
      * - `true` => enable SpeechRTC with defaults
      * - `{ enabled: true, provider: 'speechRTC'|'speech', voiceType: '...' }`
      * - `{ speechRTC: { voiceType: '...' } }`
      * - `{ speech: { voiceType: '...' } }`
     * Priority: request options -> session config -> character config -> constructor config.
     * @param {Object} [options]
     * @returns {{ enabled: boolean, provider: string, sessionOptions: Object }}
     */
    _getTextToSpeechOptions(options: DHAny): {
        enabled: boolean;
        provider: string;
        sessionOptions: any;
    };
    _normalizeAutoReadReplyValue(value: DHAny): boolean | undefined;
    _getAutoReadReplySources(options: DHAny): any[];
    _isAutoReadReplyEnabled(options?: DHAny): boolean;
    /**
     * Build SpeechRTC options for non-RTC text reply playback.
     * Defaults to mp3 + manual playback so DigitalHuman can reuse lip sync.
      * When bracketAction is enabled, bracketed action hints are excluded from
      * spoken text unless the caller explicitly disables it via
      * `textToSpeech.ignoreBracketText = false`.
     * @param {Object} [options]
     * @returns {Object}
     */
    _buildTextSpeechRTCOptions(options?: DHAny): any;
    _buildStreamingTextSpeechRTCOptions(options?: DHAny): any;
    _resolveTextSpeechContent(text: DHAny, options?: DHAny, sessionOptions?: DHAny): string;
    _resolveStreamingTextSpeechContent(text: DHAny, options?: DHAny, sessionOptions?: DHAny): string;
    _buildSpeechAudioUrl(result: DHAny, options?: DHAny): string | null;
    /**
     * Resolve muteWhileSpeaking options from request/session/config state.
     * When enabled, the mic is automatically muted while the avatar speaks
     * (text TTS or voice chat remote audio) and unmuted when speech ends.
     * A safety timer (`maxDuration`) guarantees the mic is never muted longer
     * than the configured ceiling (default 5 s).
     *
     * Supported shapes:
     *  - `true`  => enabled with defaults (maxDuration=5)
     *  - `{ enabled: true, maxDuration: 8 }`
     *
     * Priority: request options -> session config -> character config -> constructor config.
     * @param {Object} [options]
     * @returns {{ enabled: boolean, maxDuration: number }}
     */
    _getMuteWhileSpeakingOptions(options: DHAny): {
        enabled: boolean;
        maxDuration: number;
    };
    /**
     * Mute the microphone because the avatar started speaking.
     * Does nothing if muteWhileSpeaking is disabled or already active.
     * Starts a safety timer that auto-unmutes after maxDuration seconds.
     * @param {Object} [options]
     */
    _muteWhileSpeakingStart(options?: DHAny): void;
    /**
     * Unmute the microphone because the avatar stopped speaking.
     * Does nothing if not currently auto-muted.
     */
    _muteWhileSpeakingStop(): void;
    _getComfortMessageForTool(toolName: DHAny): "" | "(记录中...)" | "(查询中...)";
    _isAssistantTextSpeechPlaying(): boolean;
    _triggerComfortMessage(toolName: DHAny, options: DHAny | undefined, sentTypes: DHAny, pendingMessages: DHAny): Promise<void>;
    _startTextSpeechTurn(): Promise<any>;
    _queueTextSpeech(text: DHAny, options?: DHAny, meta?: DHAny): boolean;
    _drainTextSpeechQueue(): Promise<void>;
    _restoreIdleAfterTextSpeech(requestId: DHAny): void;
    _stopTextSpeechPlayback(): Promise<void>;
    _isStreamingTextSpeechEnabled(options?: DHAny): boolean;
    _setStreamingTextSpeechSpeaking(isSpeaking: DHAny, requestId: DHAny): void;
    _handleStreamingTextSpeechAudioChunk(bytes: DHAny, requestId: DHAny): void;
    _createStreamingTextSpeechState(options?: DHAny, meta?: DHAny): any;
    _appendStreamingTextSpeech(text: DHAny, options?: DHAny, meta?: DHAny): Promise<boolean>;
    _finishStreamingTextSpeech(text: DHAny, options?: DHAny, meta?: DHAny): Promise<any>;
    _playAudioWithLipSyncUntilEnded(audioUrl: DHAny, callbacks?: DHAny): Promise<void>;
    _speakTextResponseWithSpeechRTC(text: DHAny, options?: DHAny): Promise<any>;
    _speakTextResponseWithSpeech(text: DHAny, options?: DHAny): Promise<any>;
    _speakTextResponseNow(text: DHAny, options?: DHAny, meta?: DHAny): Promise<any>;
    _speakTextResponse(text: DHAny, options?: DHAny): Promise<null>;
    /**
     * Find the best matching custom action alias for a bracketed LLM phrase.
     * Matching is symmetric substring matching after lightweight normalization.
     * Built-in idle/talk actions are ignored to avoid false positives.
     * @param {string} bracketText
     * @returns {{ actionKey: string, matchedAlias: string }|null}
     */
    _findBracketActionMatch(bracketText: DHAny): {
        actionKey: string;
        matchedAlias: string;
    } | null;
    /**
     * Scan text for bracketed action hints and emit a deduplicated bracketAction event.
     * Only the first 500 words of the text are scanned.
     * @param {string} text
     * @param {Set<string>} seenMatches
     * @param {Object} [meta]
     * @param {{ enabled?: boolean, autoplay?: boolean, duration?: number }} [options]
     */
    _emitBracketActionEvents(text: DHAny, seenMatches: DHAny, meta?: DHAny, options?: DHAny): void;
    /**
     * Initialize avatar rendering with the given video actions.
     * Keys may contain pipe-separated aliases, e.g. '待机|idle|0': { url }.
     * @param {Object} videoActions - { "待机|idle|0": { url }, "说话|talk|1": { url } }
     * @param {Object} [options]
     * @param {boolean} [options.avatarOnlyMode] - Full screen mode (no chat overlay)
     */
    initAvatar(videoActions: DHAny, options?: DHAny): Promise<void>;
    /**
     * Get custom action alias groups, excluding idle/talk and numeric aliases.
     * @returns {string[][]}
     */
    _getCustomActionAliasGroups(): string[][];
    /**
     * Normalize action list language filter.
     * @param {string} lang
     * @returns {'en'|'zh'|null}
     */
    _normalizeActionListLang(lang: DHAny): any;
    /**
     * Get comma-separated custom action aliases, optionally filtered by language.
     * Supported language filters: enUS|zhCN|en|cn|English|Chinese.
     * @param {string} [lang]
     * @returns {string}
     */
    _getActionList(lang: DHAny): string;
    /**
     * Register the 'digitalhuman' tool category on construction, then refresh
     * its definitions after avatar actions become available.
     */
    _registerDigitalHumanTool(): void;
    /**
     * Auto-register the `minigame` copilot tool category (idempotent per SDK) and
     * subscribe this DigitalHuman to iframe events. Default `gameFinished` handling:
     *   1. Emit a `minigameEvent` event with the raw iframe data.
     *   2. Restart the agent so the LLM picks up any workspace changes made by the game.
     * Hosts can override via `this.on('minigameEvent', handler)` or by setting
     * `characterConfig.minigame.autoRestartAgent = false` to disable the restart.
     */
    _registerMinigameTool(): void;
    /**
     * Close the minigame iframe overlay (if open) and restart the agent to default.
     * @param {Object} [options]
     * @param {string} [options.reason='user'] - Close reason passed to MinigameTools.close()
     * @param {boolean} [options.restartAgent=true] - Whether to restart the agent after closing
     * @returns {Promise<void>}
     */
    closeMinigame(options?: DHAny): Promise<void>;
    /** Forward user ASR subtitles into the active minigame iframe. */
    _forwardUserVoiceInputToMinigame(data?: DHAny): void;
    _checkVideoActionsAvailable(videoActions: DHAny): boolean;
    _initializeVideos(): Promise<void>;
    _loadIdleVideo(): Promise<any>;
    _preloadTalkVideo(): Promise<any>;
    _initializeWebp(): void;
    /**
     * Show a custom webp action by swapping the talk image source.
     * @param {string} url - Webp image URL
     */
    _playWebpAction(url: DHAny): void;
    /**
     * Compute the Live2D model's rendered screen-space rectangle.
     * @returns {{ x: number, y: number, width: number, height: number, padding: number } | null}
     */
    _getLive2DModelScreenRect(): {
        x: number;
        y: number;
        width: number;
        height: number;
        padding: number;
    } | null;
    /**
     * Show a webp overlay on top of the Live2D canvas for custom actions.
     * Uses the Live2D model's actual rendered rect (which already includes
     * scale/offsetY) to size and position the webp to match.
     * @param {string} url - Webp image URL
     */
    _playLive2DWebpOverlay(url: DHAny): void;
    /**
     * Hide the webp overlay and restore the Live2D canvas.
     */
    _hideLive2DWebpOverlay(): void;
    _initializeLive2D(): Promise<void>;
    _ensureLive2DScripts(): Promise<void>;
    _getLive2DLayoutTarget(): any;
    _getLive2DViewportSize(): {
        width: number;
        height: number;
    };
    _syncLive2DViewport(force: DHAny): boolean;
    _scheduleLive2DLayout(force?: DHAny): void;
    _observeLive2DContainer(): void;
    /**
     * Get merged layout params (scale, offsetY) from idle action config + URL query.
     * URL query params override config object props.
     * offsetY is a fraction of viewport height (e.g. 0.2 = 20%).
     * @returns {{ scale: number, offsetY: number }}
     */
    _getIdleLayoutParams(): {
        scale: any;
        offsetY: any;
    };
    _layoutLive2D(): void;
    _bindLive2DLipSync(): void;
    /**
     * Set mouth open value (0-1) for lip sync.
     * @param {number} value - 0 (closed) to 1 (fully open)
     */
    setMouthOpen(value: DHAny): void;
    /**
     * Play audio via Web Audio API with lip sync analysis.
     * @param {string} audioUrl - URL of the audio to play
     * @param {Function|Object} [callbacks] - Callback or { onStart, onEnded }
     * @returns {Promise<AudioBufferSourceNode>}
     */
    playAudioWithLipSync(audioUrl: DHAny, callbacks: DHAny): Promise<any>;
    /** Stop audio-driven lip sync. */
    stopAudioLipSync(): void;
    /** Start smooth RTC lip sync animation loop. */
    _startRtcLipSync(): void;
    /** Stop RTC lip sync animation loop. */
    _stopRtcLipSync(): void;
    /** Switch avatar to idle state. */
    switchToIdle(): void;
    /** Switch avatar to talking state. */
    switchToTalking(): void;
    _performTalkTransition(): void;
    /**
     * Switch avatar to a named state. Supports aliases (e.g. 'idle', 'talk', 0, 1).
     * @param {string|number} type
     */
    switchVideo(type: DHAny): void;
    /**
     * Play a Live2D motion.
     * @param {string[]} [preferredGroups=['Tap','TapBody','Idle']]
     * @param {number} [priority=2]
     */
    playMotion(preferredGroups: DHAny, priority: DHAny): void;
    /**
     * Play a named action from videoActions for a given duration, then return to idle.
     * Supports aliases: '待机'/0 → 'idle', '说话'/1 → 'talk', plus any pipe-defined aliases.
     * If called again with the same resolved action, only the duration timer is reset.
     * @param {string|number} actionKey - Key in videoActions (e.g. '高兴', 'happy', 'talk', '说话', 1)
     * @param {number} [duration=3] - Seconds to hold the action. -1 = stay indefinitely.
     */
    playAction(actionKey: DHAny, duration?: number): void;
    /**
     * Load and play a one-off action video on the talk video element.
     * @param {string} url - Video URL
     */
    _playActionVideo(url: DHAny): void;
    /** Get current avatar control state for host. */
    getAvatarStatus(): {
        enabled: boolean;
        idleMediaType: any;
        live2dMode: boolean;
        live2dReady: boolean;
        currentVideoType: any;
        mouthOpen: number;
        hostSessionActive: boolean;
    };
    getSession(): any;
    /**
     * Manually send the configured boot message through the text chat session.
     * The boot input itself is excluded from keepHistory, while the assistant
     * reply remains in the session like any other reply.
     * @param {string} [bootMessage] - Override message; defaults to characterConfig.initial.bootMessage
     * @param {Object} [options]
     * @returns {Promise<{ finalText: string, parsedResponse: Object, mode: 'text', skipped?: boolean, reason?: string }>}
     */
    sendBootMessage(bootMessage: DHAny, options?: DHAny): Promise<any>;
    /**
     * Enable remote control via postMessage. Listens for messages and calls methods on this instance.
     * @param {Object} options
     * @param {string} options.msgPrefix - Prefix for message types
     * @param {Function} options.postToParent - Function to send messages back
     * @param {Function} [options.setupToolProxy] - Optional hook to modify config before init
     * @param {boolean} [options.forwardUserVoiceInputViaParentFrame] - Let the parent DigitalHumanFrame forward user voice text to minigames.
     */
    enableRemoteControl(options?: DHAny): void;
    _normalizeHostMouthValue(payload: DHAny): number | null;
    /** Ensure Live2D model is ready (initializes if needed). */
    ensureLive2DReady(): Promise<{
        enabled: boolean;
        idleMediaType: any;
        live2dMode: boolean;
        live2dReady: boolean;
        currentVideoType: any;
        mouthOpen: number;
        hostSessionActive: boolean;
    }>;
    startHostLive2DCall(payload?: DHAny): Promise<{
        enabled: boolean;
        idleMediaType: any;
        live2dMode: boolean;
        live2dReady: boolean;
        currentVideoType: any;
        mouthOpen: number;
        hostSessionActive: boolean;
    }>;
    updateHostLive2DCall(payload?: DHAny): Promise<{
        enabled: boolean;
        idleMediaType: any;
        live2dMode: boolean;
        live2dReady: boolean;
        currentVideoType: any;
        mouthOpen: number;
        hostSessionActive: boolean;
    }>;
    stopHostLive2DCall(): {
        enabled: boolean;
        idleMediaType: any;
        live2dMode: boolean;
        live2dReady: boolean;
        currentVideoType: any;
        mouthOpen: number;
        hostSessionActive: boolean;
    };
    /**
     * Initialize the DigitalHuman from a characterManager-style config object.
     * This is a convenience method that sets up avatar, AI session, and stores
     * all character metadata in one call.
     *
     * The config object mirrors the format produced by characterManager's
     * `buildCharacterConfig`, with the same nested structure:
     *
     * @param {Object} config - characterManager-style config (all fields stored in dh.characterConfig)
     * @param {string}  [config.system_prompt]        - System prompt for LLM
     * @param {boolean} [config.enable_system_prompt] - Whether system prompt is active (default true)
     * @param {string|Object} [config.llm_model]      - Model name string or { model, temperature, knowledgeUsername, knowledgeBaseCodes, reasoning }
     * @param {Object}  [config.videoActions]         - { '待机': { url }, '说话': { url }, ... }
    * @param {Object}  [config.tools]                - { fileOps: { enabled, workspace, ... }, web: { enabled }, ... }
    * @param {Array}   [config.searchPaths]           - Search paths for readFile URL fallback: [{ prefix, baseUrl }]
    * @param {boolean|Object} [config.bracketAction] - `true` emits bracketAction events; object form also supports autoplay/duration; parsing is limited to the first 500 words
      * @param {boolean|Object} [config.textToSpeech] - Non-RTC assistant reply speech; `true` enables SpeechRTC defaults, object form accepts `speechRTC` or `speech` provider options. Set `autoReadReply: false` to keep manual TTS available but stop automatically reading assistant replies.
     * @param {Object}  [config.initial]              - Initial greeting config
     * @param {string}  [config.initial.message]       - Static welcome message (displayed directly)
    * @param {string}  [config.initial.bootMessage]   - Boot message template; call sendBootMessage() manually after restoring any history
     * @param {boolean} [config.avatar_only]          - Avatar-only display mode
    * @param {boolean|Object} [config.keepHistory]    - Persist rounds to history.md; `true` or `{ historyLength, fileName, keepFullHistory }`
    * @param {boolean} [config.keepFullHistory]        - Also persist full daily history to history/history_YYYYMMDD.md
     * @param {Object}  [config.summarizeAgent]        - Dedicated summarize agent config
     * @param {string}  [config.summarizeAgent.config]  - URL or path to the agent's config file (YAML/JSON/MD)
     * @param {number}  [config.summarizeAgent.silentTickInterval] - Periodic summarization interval in seconds
     * @param {number}  [config.summarizeAgent.maxRounds]          - Threshold: max conversation rounds before triggering
     * @param {number}  [config.summarizeAgent.maxTextLength]      - Threshold: max total text length before triggering
     * @param {number}  [config.summarizeAgent.keepRecentRounds]   - Number of recent rounds to preserve
     * @param {string}  [config.summarizeAgent.mode]               - 'replace' (compress history) or 'append' (return summary only)
     *
     * @returns {Promise<Object>} { session, config, bootResponse? }
     */
    initFromConfig(config?: DHAny): Promise<{
        session: any;
        config: any;
    }>;
    /**
     * Detect format of a URL by extension (stripping query/fragment).
     * @deprecated Use AgentConfig.detectFormat() instead.
     */
    static _detectConfigFormat(url: DHAny): import("../core/AgentConfig").AgentConfigFormat | null;
    /**
     * Normalize a parsed config object.
     * @deprecated Use AgentConfig.normalize() instead.
     */
    static _normalizeConfig(config: DHAny): import("../core/AgentConfig").NormalizedAgentConfig;
    /**
     * Fetch and parse a DigitalHuman config from a URL, JSON string, or object.
     * Delegates to AgentConfig.fetch().
     *
     * @param {string|Object} source - URL string, JSON string, or config object
     * @returns {Promise<Object>} Parsed and normalized config object
     */
    static fetchConfig(source: DHAny): Promise<import("../core/AgentConfig").NormalizedAgentConfig>;
    /**
     * Load a DigitalHuman config from a URL (JSON / YML / MD), inline JSON string, or object,
     * then initialize the avatar and AI session in one call.
     *
     * This is the simplest way to set up a DigitalHuman — just point it at a config file:
     *   await dh.loadConfig('https://example.com/character.md');
     *
     * Equivalent to:
     *   const config = await DigitalHuman.fetchConfig(source);
     *   await dh.initFromConfig(config);
     *
     * @param {string|Object} source - URL string, JSON string, or config object
     * @returns {Promise<Object>} Result of initFromConfig: { session, config }
     */
    loadConfig(source: DHAny): Promise<{
        session: any;
        config: any;
    }>;
    /**
     * Build LLM configuration from session config.
     * @param {Object} [config] - Override config
    * @returns {Object} LLM config for sdk.aiChat.createSession()
     */
    _getLLMConfig(config: DHAny): any;
    /**
     * Apply FileOps workspace/pathPrefix configuration to a session.
     * @param {Object} session - ChatSession
     * @param {Object} [config] - Override config
     */
    _applyFileOpsConfig(session: DHAny, config: DHAny): void;
    /**
     * Pass summarization YAML config to the CopilotTools `summarize` category
     * so that `summarize_conversation` tool calls receive the configured prompt,
     * model, enableTools, keepRecentRounds, and mode.
     * @param {Object} [config]
     */
    _applySummarizationToolConfig(config: DHAny): void;
    /**
     * Build daily full-history file path: history/history_YYYYMMDD.md
     * @param {Date} [date]
     * @returns {string}
     */
    _getKeepHistoryDailyFileName(date?: Date): string;
    /**
     * Read a file via the session sandbox (respects tool proxy), falling back to direct store access.
     * @param {string} fileName
     * @returns {Promise<string>}
     */
    _keepHistoryReadFile(fileName: DHAny): Promise<any>;
    /**
     * Create/overwrite a file via the session sandbox (respects tool proxy), falling back to direct store access.
     * @param {string} fileName
     * @param {string} content
     * @returns {Promise<string>}
     */
    _keepHistoryCreateFile(fileName: DHAny, content: DHAny): Promise<any>;
    /**
     * Format a timestamp as local wall-clock time for history comments.
     * @param {number|Date|string} value
     * @returns {string}
     */
    _formatKeepHistoryTimestamp(value: DHAny): string;
    /**
     * Normalize timestamp values from history comments or in-memory message fields.
     * @param {number|Date|string} value
     * @returns {number|null}
     */
    _parseKeepHistoryTimestamp(value: DHAny): number | null;
    /**
     * Convert messages into markdown blocks with per-message timestamps.
     * @param {Array<Object>} targetMessages
     * @returns {{ content: string, entries: Array<{ timestamp: number|null, markdown: string }> }}
     */
    _buildKeepHistoryMarkdown(targetMessages: DHAny): {
        content: string;
        entries: {
            timestamp: number | null;
            markdown: string;
        }[];
    };
    /**
     * Read timestamped user blocks from a history markdown file.
     * @param {string} md
     * @returns {Array<{ timestamp: number|null, markdown: string }>}
     */
    _parseKeepHistoryEntries(md: DHAny): {
        timestamp: number | null;
        markdown: string;
    }[];
    /**
     * Initialize keepHistory on createSession. Reads existing history.md,
      * parses it back into user/assistant messages, and injects them into the
      * session.
      *
      * Important behavior: this only restores prior context. It does not call
      * `summarize()` automatically, even if the restored conversation already
      * exceeds summarization thresholds.
     * @param {Object} config - createSession config
     */
    _initKeepHistory(config: DHAny): Promise<void>;
    /**
    * Parse history.md markdown back into session messages.
    * Expects `<!-- ts:YYYY-MM-DD HH:mm:ss -->` timestamps before ## User sections.
     * If a message pair is older than 2 hours, the user message content is
     * prefixed with `[YYYY-MM-DD HH:mm]` so the LLM has temporal context.
     * @param {string} md - Raw markdown content
    * @returns {Array<{ role: string, content: string, _ts?: number }>}
     */
    _parseHistoryMd(md: DHAny): ({
        role: string;
        content: any;
        _ts: number;
    } | {
        role: string;
        content: any;
        _ts?: undefined;
    })[];
    /**
     * Save current conversation messages to history.md in the workspace.
     * Called after each message round completes.
     * Only saves the most recent `historyLength` rounds (user+assistant pairs).
     * @param {Object} [options]
     * @param {boolean} [options.skipDailyFile=false] - Skip daily file writes (used after summarization)
     */
    _saveKeepHistory(options?: DHAny): Promise<void>;
    /**
     * Called when any summarization completes (manual, auto, silentTick).
     * Updates the keepHistory cutoff so _saveKeepHistory won't re-save
     * messages that the summarize agent has already processed.
     * Also trims history.md to remove already-summarized content.
     * @param {Object} result - Summarization result with summarizeBeginTime
     */
    _onSummarizeComplete(result: DHAny): void;
    /**
     * Keep exactly one system message at the start of the chat history.
     * This avoids losing the configured prompt when sessions are recreated or
     * when callers mix pre-seeded messages with DigitalHuman-managed prompts.
     * @param {string} prompt
     */
    _syncSessionSystemPrompt(prompt: DHAny): void;
    /**
     * Create a new AI chat session.
     * @param {Object} config - Session configuration
     * @param {string} [config.system_prompt] - System prompt
     * @param {string|Object} [config.llm_model] - LLM model name or config object
    * @param {Object} [config.tools] - Tool configuration { fileOps: { enabled, workspace }, ... }
    * @param {boolean|Object} [config.bracketAction] - `true` emits bracketAction events; object form also supports autoplay/duration; parsing is limited to the first 500 words
      * @param {boolean|Object} [config.textToSpeech] - Non-RTC assistant reply speech; `true` enables SpeechRTC defaults, object form accepts `speechRTC` or `speech` provider options
    * @param {boolean|Object} [config.keepHistory] - Persist conversation to history.md in workspace; `true` or `{ historyLength, fileName, keepFullHistory }`
    * @param {boolean} [config.keepFullHistory] - Also persist full daily history to history/history_YYYYMMDD.md
     * @returns {Promise<Object>} The created ChatSession
     */
    createSession(config?: DHAny): Promise<any>;
    /**
     * Unified send — auto-routes to voice or text session.
     *
     * When voice chat is active, sends via the RTC voice channel by default and
     * also records the user message into the canonical text ChatSession so history
     * stays unified. When voice chat is inactive, sends through the text AIChat
     * session (identical to the legacy sendMessage behaviour).
     *
     * @param {string|Array} userMessage - Text or multimodal content
     * @param {Object}  [options]
     * @param {boolean} [options.voice]         - Force voice (true) or text (false); auto-detect if omitted
     * @param {boolean} [options.awaitResponse] - Voice mode only: if true, wait for the assistant's complete subtitle turn before resolving
    * @param {boolean} [options.skipHistory]   - Skip session/keepHistory persistence for this message round
     * @param {Array}   [options.tools]         - Additional tool definitions (text mode)
     * @param {string}  [options.model]         - Override model (text mode)
    * @param {boolean} [options.skipIfMessageTextEmpty] - Text mode: skip when runCode resolves to an empty string
    * @param {boolean|Object} [options.textToSpeech] - Override non-RTC assistant reply speech; object form accepts `speechRTC` or `speech` provider options. Set `autoReadReply: false` to disable automatic reply playback for this send.
     * @param {boolean|Object} [options.bracketAction] - Bracket action config
     * @returns {Promise<{ finalText: string, parsedResponse?: Object, mode: 'voice'|'text' }>}
     */
    send(userMessage: DHAny, options?: DHAny): Promise<any>;
    _getUserMessageText(userMessage: DHAny): string;
    _emitUserMessage(userMessage: DHAny, mode?: string, extra?: DHAny): void;
    /**
     * Send a message through the voice RTC session.
     * Also mirrors the user message into the text ChatSession for unified history.
     * @private
     */
    _sendViaVoice(userMessage: DHAny, options?: DHAny): Promise<{
        finalText: string;
        mode: string;
        skipped: boolean;
        reason: string | undefined;
    } | {
        finalText: unknown;
        mode: string;
        skipped?: undefined;
        reason?: undefined;
    }>;
    _beginTextSend(): {
        epoch: any;
        session: any;
        abortController: AbortController | null;
        canceled: boolean;
        reason: string;
    };
    _finishTextSend(state: DHAny): void;
    _isCurrentTextSend(state: DHAny): boolean;
    _cancelActiveTextSends(reason?: string): Promise<number>;
    _isTextSendAbort(error: DHAny): boolean;
    _clearQueuedTextSends(reason?: string): any;
    _sendViaText(userMessage: DHAny, options?: DHAny): Promise<any>;
    _drainTextSendQueue(): Promise<void>;
    /**
     * Send a message through the text AIChat session (the full streaming path).
     * @private
     */
    _sendViaTextNow(userMessage: DHAny, options?: DHAny): Promise<DHAny>;
    /**
     * Send a message via the text AI chat session with streaming callbacks emitted as events.
     * Backward-compatible alias — always uses the text path regardless of voice state.
     * @param {string|Array} userMessage - Text or multimodal content
     * @param {Object} [options]
     * @param {Array} [options.tools] - Additional tool definitions
    * @param {string} [options.model] - Override model for this request
    * @param {boolean} [options.runCode] - Process userMessage as template text, expanding ${...} expressions via sandbox
    * @param {boolean} [options.skipHistory] - Skip session/keepHistory persistence for this message round
    * @param {boolean|Object} [options.textToSpeech] - Override non-RTC assistant reply speech; object form accepts `speechRTC` or `speech` provider options
    * @param {boolean|Object} [options.bracketAction] - Override bracketAction behavior for this request; object form supports autoplay/duration; parsing is limited to the first 500 words
     * @returns {Promise<{ finalText: string, parsedResponse: Object }>}
     */
    sendMessage(userMessage: DHAny, options?: DHAny): Promise<any>;
    /**
     * Expand an inline system prompt using the iframe session's sandbox.
     * This ensures preview/debug views resolve ${...} the same way as the
     * actual in-iframe DigitalHuman session.
     * @param {string} text
     * @returns {Promise<string>}
     */
    expandInlineSystemPrompt(text: DHAny): Promise<any>;
    /**
     * @returns {boolean} Whether voice chat is currently active
     */
    get isActive(): any;
    /**
     * @returns {boolean} Whether voice chat is logically enabled, even if the RTC connection is paused while inactive
     */
    get isVoiceChatModeActive(): any;
    get isVoiceChatActive(): boolean;
    /**
     * Start voice chat using AIChatRTC.
     * @param {Object} preset - Voice chat preset config (see AIChatRTC.createSession)
     * @param {string} preset.appId - VolcEngine AppId
     * @param {Object} [preset.agentConfig] - Agent config
     * @param {Object} [preset.config] - ASR/LLM/TTS/S2S config
      * @param {boolean|Object} [preset.bracketAction] - Apply bracketAction matching to AI messages; parsing is limited to the first 500 words
     * @param {string[]} [preset.enabledToolCategories] - Tool categories
     * @param {string} [preset.workspace] - Tool workspace
     * @returns {Promise<Object>} The RTC session
     */
    /**
     * Default ASR/LLM/TTS config for voice chat (asr_llm_tts mode).
     * Used when `preset.config` is not provided in `startVoiceChat()`.
     */
    static DEFAULT_VOICE_CHAT_CONFIG: {
        appId: string;
        agentUserId: string;
        agentConfig: {
            UserId: string;
            EnableConversationStateCallback: boolean;
        };
        config: {
            ASRConfig: {
                Provider: string;
                ProviderParams: {
                    Mode: string;
                    AppId: string;
                    ApiResourceId: string;
                };
            };
            TTSConfig: {
                Provider: string;
                ProviderParams: {
                    app: {
                        appid: string;
                    };
                    audio: {
                        voice_type: string;
                        speech_rate: number;
                    };
                    ResourceId: string;
                };
            };
            LLMConfig: {
                Mode: string;
                EndPointId: string;
                VisionConfig: {
                    Enable: boolean;
                };
                ThinkingType: string;
                Tools: never[];
            };
            SubtitleConfig: {
                SubtitleMode: number;
            };
            InterruptMode: number;
        };
    };
    /**
     * Build a complete voice chat preset by merging caller-supplied high-level
     * params (system_prompt, llm_model, workspace, tools, etc.) onto the
     * DEFAULT_VOICE_CHAT_CONFIG.  If the caller already supplies `preset.config`
     * the default config block is skipped entirely so existing call-sites keep working.
     * @param {Object} preset - Caller-supplied preset
     * @returns {Object} Merged preset ready for AIChatRTC.createSession()
     */
    _buildVoiceChatPreset(preset: DHAny): any;
    startVoiceChat(preset?: DHAny, options?: DHAny): Promise<DHAny>;
    /**
     * Stop voice chat.
     * @returns {Promise<void>}
     */
    stopVoiceChat(): Promise<void>;
    handleAuthStateChange(change?: DHAny): Promise<any>;
    reloadForAuthChange(change?: DHAny): Promise<any>;
    /**
     * Restart the voice chat session with optional config overrides.
     * When possible, updates the active RTC agent in place via UpdateVoiceChat
     * so the room connection is kept alive. Falls back to a full restart if the
     * update API is unavailable or fails. Useful when the system prompt,
     * LLM config, or conversation history has changed (e.g. after
     * summarize-agent completes in replace mode, or when enabling vision).
     *
     * @param {Object} [configOverrides] - Partial preset overrides to deep-merge
     *   into `_lastVoiceChatPreset`.  Nested objects under `config` are merged
     *   recursively; all other top-level keys are shallow-merged.
     * @returns {Promise<Object>} The new RTC session
     */
    restartVoiceChat(configOverrides?: DHAny): Promise<any>;
    /** @private */
    _resolveRestartAgentPromptFile(promptFile: DHAny): string | null;
    /** @private */
    _cancelRestartAgentDebounce(result?: DHAny): boolean;
    /** @private */
    _getRestartAgentDedupeMs(options?: DHAny): number;
    /** @private */
    _getRestartAgentDedupeKey(promptFile: DHAny, tools?: DHAny[]): string | null;
    /** @private */
    _buildRestartAgentSkippedResult(promptFile: DHAny, tools: DHAny, reason: DHAny, extra?: DHAny): any;
    /**
     * Restart the agent session with an optional prompt file.
     * Handles both voice and text chat modes — stops voice if active,
     * re-initializes via initFromConfig, then restarts voice if it was active.
     *
     * @param {string} [promptFile] - URL or path to an agent config file (.json/.yml/.yaml/.md).
     *   If empty, uses the current pageRouters entry agent first, then falls back to the current characterConfig.
     * @param {string[]} [tools] - Optional tool category override. Empty means inherit defaults.
     * @param {Object} [options]
     * @param {number} [options.debounceMs=0] - Delay empty-prompt restarts; cancelled by any later explicit prompt restart.
    * @param {boolean} [options.autoContinue=true] - Automatically send "(continue)" after a prompt-file restart.
     * @returns {Promise<Object>} { configSource, mode }
     */
    restartAgent(promptFile: DHAny, tools: DHAny, options?: DHAny): Promise<any>;
    /** @private */
    _restartAgentImpl(promptFile: DHAny, tools: DHAny, options?: DHAny): Promise<{
        mode: string;
        loaded: boolean;
        configSource: any;
        workspace: any;
        mountFolder: any;
        toolCategories: string[];
    }>;
    /**
     * Send text during voice chat.
     * Also mirrors the user message into the canonical text ChatSession.
     * @param {string} text
     */
    sendText(text: DHAny): void;
    /**
     * Send text to TTS (text-to-speech) and play it through the avatar.
     * - Voice chat active: delegates to RTCChatSession.sendTTS (binary/REST).
     * - Text mode: queues the text through the text-mode speech pipeline
     *   (same as assistant responses) so the avatar speaks it out.
     * @param {string} text
     * @param {Object} [options]
     * @param {boolean} [options.useREST=false] - Voice mode only: use REST API instead of binary channel
     * @param {number} [options.interruptMode] - Voice mode only: REST interrupt priority
     */
    sendTTS(text: DHAny, options?: DHAny): any;
    /**
     * Get the current RTC voice chat session (for advanced control).
     * @returns {Object|null}
     */
    getVoiceChatSession(): any;
    /**
     * Wait until the voice chat session has received its first state event
     * (UNKNOWN/0 or higher). Resolves immediately if already ready, or if
     * no voice session is active.
     * @param {number} [timeout=10000] - Max milliseconds to wait
     * @returns {Promise<boolean>} true if ready, false if timed out or no session
     */
    waitUntilVoiceReady(timeout?: number): Promise<unknown>;
    /**
     * Mirror a voice chat turn into the canonical text ChatSession's messages array.
     * This keeps the text session as the single source of truth for conversation history.
     * User messages are committed only in IO pairs:
     * - queue one or more user inputs
     * - on assistant reply, merge queued user inputs into one message, then append assistant message
     * @param {'user'|'assistant'} role
     * @param {string} content
     * @param {Object} [extras] - Optional: { tool_calls, tool_call_id, source, skipHistory }
     */
    _mirrorVoiceToTextSession(role: DHAny, content: DHAny, extras?: DHAny): void;
    /**
     * Build UserPrompts for LLMConfig from normalized text-session history.
     * The result is always strict user/assistant pairs. If the sequence starts
     * with an assistant message, an empty user turn is inserted ahead of it.
     * Consecutive same-role turns are merged before pairing.
     * @param {number} historyLength - Number of user/assistant pairs to include
     * @returns {Array<{ Role: string, Content: string }>}
     */
    _buildUserPromptsForVoice(historyLength?: number): any[];
    /** Wire RTCChatSession events to DigitalHuman events. */
    _wireVCSessionEvents(session: DHAny, bracketActionOptions?: DHAny): void;
    /** Attach volume-based lip sync to the RTC engine for smooth mouth animation. */
    _attachVolumeLipSync(session: DHAny): void;
    /** Clean up avatar state (reusable — does not remove DOM). */
    cleanupAvatar(): void;
    /** Fully destroy the DigitalHuman instance. */
    destroy(): Promise<void>;
}
export {};
//# sourceMappingURL=DigitalHuman.d.ts.map