/**
 * Agent Manager - Manages Agent instances per session
 *
 * Each session gets its own Agent instance for true isolation
 * and concurrent processing across sessions.
 */
import { Agent, type AgentMessage, type AgentEvent, type ThinkingLevel } from '@earendil-works/pi-agent-core';
import type { AgentInstanceGateway } from './agent-instance-gateway.js';
import { type Config } from '../config/schema.js';
import { type EffectiveAgentProfile } from '../config/agent-profile.js';
import type { ModelManager } from './models/manager.js';
import type { GatewayClarifyRequestFn } from './tools/clarify-tool.js';
import type { ExtensionRegistryImpl as ExtensionRegistry } from '../extensions/index.js';
import type { MessageBus } from '../infra/bus/index.js';
import type { CronService } from '../cron/index.js';
import type { SessionStore } from '../session/store.js';
import type { SessionContext } from './session/session-context.js';
import type { Skill, SkillMarkdownPreviewPayload } from './skills/types.js';
import { type SkillHubLockEntry } from './skills/hub-lock.js';
import type { MemoryManager } from './memory/manager.js';
export interface SkillCatalogEntry {
    directoryId: string;
    name: string;
    description: string;
    source: Skill['source'];
    path: string;
    managed: boolean;
    /** User toggle in ~/.xopc/skills.json (`entries[name].enabled`). Default true. */
    enabled: boolean;
    /** When true, skill is never injected into `<available_skills>` (SKILL.md frontmatter). */
    disableModelInvocation: boolean;
    /** Hub install provenance when under ~/.xopc/skills and listed in skills-lock.json. */
    hub?: SkillHubLockEntry;
}
export interface AgentManagerConfig {
    workspace: string;
    model?: string;
    config?: Config;
    extensionRegistry?: ExtensionRegistry;
    hookRunner?: import('../extensions/index.js').ExtensionHookRunner;
    bus: MessageBus;
    getCurrentContext: () => SessionContext | null;
    /** Session persistence (enables `session_search` when set). */
    getSessionStore?: () => SessionStore;
    /** Clears per-session profile default on teardown. */
    getModelManager?: () => ModelManager;
    thinkingLevel?: ThinkingLevel;
    reasoningLevel?: 'off' | 'on' | 'stream';
    verboseLevel?: 'off' | 'on' | 'full';
    gatewayClarify?: {
        requestClarification: GatewayClarifyRequestFn;
    };
    /** Gateway: exposes CronService for the `cronjob` tool. */
    getCronService?: () => CronService | undefined;
}
export interface AgentInstance {
    agent: Agent;
    sessionKey: string;
    createdAt: number;
    lastUsedAt: number;
    effectiveProfile: EffectiveAgentProfile;
    resolvedWorkspacePath: string;
    /** Tool names registered on this agent (for skill indexing / tool gating). */
    registeredToolNames: string[];
    /** Declared env var names from skill_view; shell reads values from process.env at spawn time. */
    skillEnvPassthroughKeys: Set<string>;
}
export declare class AgentManager implements AgentInstanceGateway {
    private agents;
    private config;
    private toolsFactory;
    private mergedConfig;
    /** Default agent workspace (effective profile for `getDefaultAgentId`). */
    private baseWorkspacePath;
    /** Per-session absolute markdown workspace when `SessionAgentConfig.workingDirectoryOverride` is set. */
    private sessionWorkspaceOverrides;
    private defaultModel;
    private credentialCache;
    private credentialResolver;
    private workspaceRuntimes;
    private memoryPrefetch;
    private backgroundReview;
    constructor(config: AgentManagerConfig);
    private computeBaseWorkspacePath;
    /**
     * Workspace root for inbound attachments / side effects for this session's agent id.
     * Uses in-memory session workspace overrides when the session has a persisted `workingDirectoryOverride`.
     */
    getResolvedWorkspaceForSession(sessionKey: string): string;
    /**
     * Sync in-memory workspace override from session config (after load or PATCH).
     * Pass `null` to clear when the session has no `workingDirectoryOverride` on disk.
     */
    setSessionWorkspaceOverride(sessionKey: string, absolutePath: string | null): void;
    /** Merged `thinkingDefault` for this session's agent id (defaults + `agents.list`). */
    getThinkingDefaultForSession(sessionKey: string): import('./transcript/thinking-types.js').ThinkLevel | undefined;
    private pickDefaultModelRef;
    private resolveModelStringToModel;
    /**
     * Keep defaults in sync when config is hot-reloaded or saved from the UI.
     *
     * The previous implementation rebuilt the entire `AgentToolsFactory` (80+ lines
     * of dependency wiring) on every reload. The factory's deps are now built from
     * a single helper ({@link buildToolsFactoryDeps}) and read `this.*` through
     * closures, so existing instances automatically see the new config without
     * reconstruction. The browser is still shut down because its cached settings
     * (headless mode, backend choice) come from the config snapshot at connect time.
     */
    updateAgentDefaults(config: Config): void;
    /**
     * Construct the dep bag passed to `AgentToolsFactory`. Closures reference
     * `this.*` so they remain valid across hot reloads (no rebuild needed).
     */
    private buildToolsFactoryDeps;
    getMemoryManager(): MemoryManager;
    private getMemoryManagerForSession;
    /**
     * Prefix the user turn with fenced prefetched memory (external providers).
     * Delegates to {@link MemoryPrefetchCoordinator}.
     */
    applyMemoryPrefetchToUserMessage(userMessage: AgentMessage, sessionKey: string): Promise<AgentMessage>;
    /**
     * After a completed turn: sync external providers and queue next-turn prefetch.
     * Delegates to {@link MemoryPrefetchCoordinator}.
     */
    afterAgentTurn(sessionKey: string, userPlainText: string): void;
    /**
     * Call once per user turn before the main `agent.prompt` (via {@link runAgentTurnWithModelFallbacks} `beforeUserPrompt`).
     * Delegates to {@link BackgroundReviewCoordinator}.
     */
    beginBackgroundReviewUserTurn(sessionKey: string): void;
    /**
     * After a successful main turn (after memory sync via `afterAgentTurn`), may run a quiet follow-up for memory/skills.
     * Delegates to {@link BackgroundReviewCoordinator}.
     */
    scheduleBackgroundReviewAfterUserTurn(sessionKey: string): void;
    /**
     * Expand `/skill:name` user text into the full skill block for the current turn (WebChat, channels).
     */
    expandSkillUserText(text: string): string;
    /**
     * Structured SKILL.md preview for the gateway console.
     * When `lang` is provided (e.g. "zh"), tries SKILL-{lang}.md first; falls back to SKILL.md.
     */
    getSkillMarkdownSource(skillName: string, lang?: string): SkillMarkdownPreviewPayload | null;
    private loadProfileMarkdownForProfile;
    private resolveContextFilesForSession;
    getSkillCatalog(lang?: string): SkillCatalogEntry[];
    /**
     * After ~/.xopc/skills.json changes (enable/disable), refresh `<available_skills>` on active agents.
     */
    refreshSkillsAfterSkillConfigChange(): void;
    /**
     * Reload skills from disk and refresh system prompt on all active Agent instances.
     */
    refreshSkillsAfterDiskChange(): void;
    /**
     * Get or create an Agent instance for a session
     */
    getOrCreateAgent(sessionKey: string): Agent;
    /**
     * Get existing agent for a session (if any)
     */
    getAgent(sessionKey: string): Agent | undefined;
    /**
     * Check if an agent exists for a session
     */
    hasAgent(sessionKey: string): boolean;
    /**
     * Remove an agent instance
     */
    removeAgent(sessionKey: string): boolean;
    /**
     * Get all active session keys
     */
    getActiveSessions(): string[];
    /**
     * Get agent count
     */
    getAgentCount(): number;
    /**
     * Set thinking level for a session's agent
     */
    setThinkingLevel(sessionKey: string, level: ThinkingLevel): void;
    /**
     * Dispose all agents
     */
    dispose(): void;
    warmCredentialCache(): Promise<void>;
    refreshCredentials(): Promise<void>;
    private resolveApiKeyWithCache;
    private createAgentForProfile;
    /**
     * Set model for a specific session
     */
    setModelForSession(sessionKey: string, modelId: string): boolean;
    /**
     * Get last assistant content from a session's agent
     */
    getLastAssistantContent(sessionKey: string): string | null;
    /**
     * Replace messages for a session's agent
     */
    replaceMessages(sessionKey: string, messages: AgentMessage[]): boolean;
    /**
     * Get messages for a session's agent
     */
    getMessages(sessionKey: string): AgentMessage[] | null;
    /**
     * Subscribe to agent events for a session
     */
    subscribeToSession(sessionKey: string, callback: (event: AgentEvent) => void): (() => void) | null;
}
