import { Adapter } from '@posthog/shared';
import { AgentMode } from '../types.js';
import { RemoteMcpServer } from './schemas.js';
import '@posthog/shared/domain-types';
import 'zod/v4';

interface RtkSavingsSummary {
    totalCommands: number;
    inputTokens: number;
    outputTokens: number;
    tokensSaved: number;
}

interface ClaudeCodeConfig {
    systemPrompt?: string | {
        type: "preset";
        preset: "claude_code";
        append?: string;
    };
    plugins?: {
        type: "local";
        path: string;
    }[];
}
interface AgentServerConfig {
    port: number;
    agentStateDir?: string;
    repositoryPath?: string;
    repoReadyFile?: string;
    apiUrl: string;
    apiKey: string;
    projectId: number;
    jwtPublicKey: string;
    eventIngestToken?: string;
    eventIngestBaseUrl?: string;
    eventIngestStreamWindowMs?: number;
    eventIngestKeepStreamOpen?: boolean;
    mode: AgentMode;
    taskId: string;
    runId: string;
    createPr?: boolean;
    autoPublish?: boolean;
    version?: string;
    mcpServers?: RemoteMcpServer[];
    /**
     * Names of desktop-only local MCP servers to expose through loopback relay
     * endpoints (docs/cloud-mcp-relay.md). Names only; the desktop resolves
     * each name against local config at execution time.
     */
    relayMcpServers?: string[];
    baseBranch?: string;
    claudeCode?: ClaudeCodeConfig;
    allowedDomains?: string[];
    runtimeAdapter?: Adapter;
    model?: string;
    reasoningEffort?: "low" | "medium" | "high" | "xhigh" | "max";
    resolveRtkSavings?: () => Promise<RtkSavingsSummary | null>;
}

declare const UPSTREAM_PROVIDER_FAILURE_MESSAGE = "The upstream AI provider failed to process the request. Please retry the task in a few minutes.";
declare const SSE_KEEPALIVE_INTERVAL_MS = 25000;
declare function isTurnCompleteNotification(message: unknown): boolean;
declare class AgentServer {
    private config;
    private sessionReadyBootMs?;
    private sessionInitMs?;
    private barrierReleasedAtMs?;
    private logger;
    private server;
    private session;
    private app;
    private posthogAPI;
    private eventStreamSender;
    private rtkSavingsAttempted;
    private questionRelayedToSlack;
    private adapterEmittedTurnComplete;
    private suppressAdapterTurnComplete;
    private runUsage;
    private detectedPrUrl;
    private readonly evaluatedPrUrls;
    private prAttributionChain;
    private lastReportedBranch;
    private resumeState;
    private nativeResume;
    private oversizedResumeRetried;
    private prewarmedRun;
    private warmAutoPublishResolved;
    private installedSkillBundles;
    private installedSkillBundleInfo;
    private installingSkillBundles;
    private initializationPromise;
    private pendingEvents;
    /** ACP notifications emitted by newSession/resumeSession before this.session is assigned. */
    private preSessionEvents;
    private deliveredMessageIds;
    private pendingCompactContinuationMessageIds;
    private pendingPermissions;
    private mcpRelayServer;
    /**
     * Start loopback relay endpoints for the run's designated desktop-only MCP
     * servers and return their session mcpServers entries. No designations →
     * no relay server, no entries.
     */
    private startMcpRelayServer;
    private detachSseController;
    private emitConsoleLog;
    constructor(config: AgentServerConfig);
    private getRuntimeAdapter;
    private getEffectiveMode;
    private getSessionPermissionMode;
    private hasReachableClient;
    private shouldRelayPermissionToClient;
    private createApp;
    start(): Promise<void>;
    private loadResumeState;
    private prepareNativeResume;
    private getNativeGoalForFreshSession;
    stop(): Promise<void>;
    /**
     * Mark the run failed after an unrecoverable crash (uncaught exception /
     * unhandled rejection). Without this a hard death is silent: the run row
     * stays non-terminal, the desktop client just sees the stream stop and shows
     * a generic "Cloud stream disconnected", and the workflow only gives up after
     * the multi-hour inactivity timeout. Best-effort and self-contained so it can
     * run from a process-level handler with no session context.
     */
    reportFatalError(error: unknown): Promise<void>;
    private authenticateRequest;
    private executeCommand;
    private initializeSession;
    private _doInitializeSession;
    private extractErrorClassification;
    /**
     * Send an initial/resume turn prompt, absorbing transient upstream
     * failures with a bounded number of retries. These turns run unattended
     * (no user watching who could retry), so without this a single transient
     * transport cut fails the whole run. A stream that died mid-response has
     * already delivered the original prompt into the session history, so that
     * case retries with a hidden continuation; failures where the request may
     * never have been processed re-send the original prompt instead.
     */
    private promptWithUpstreamRetry;
    private handleTurnFailure;
    private broadcastTurnFailure;
    private sendInitialTaskMessage;
    private sendResumeMessage;
    private sendResumeContinuation;
    /**
     * A native resume replays the prior transcript verbatim; when that
     * transcript no longer fits the context window, every request (including
     * auto-compaction) is rejected, so the only way forward is a fresh session
     * seeded with the summarized history the non-native resume path uses.
     */
    private retryOversizedResumeOnFreshSession;
    private runResumeTurn;
    private applyResumeGitCheckpoint;
    private getInitialPromptOverride;
    private getPendingUserPrompt;
    private resolvePendingArtifactManifest;
    private refetchRunArtifacts;
    private getClearedPendingUserState;
    private clearPendingInitialPromptState;
    private buildPromptFromContentAndArtifacts;
    private getArtifactsById;
    private hydrateArtifactsToPrompt;
    private installSkillBundleArtifacts;
    private buildInstalledSkillPromptContext;
    /**
     * Fallback for messages that install skill bundles without being a bare
     * `/skill` invocation: a running session can't discover mid-session
     * installs, so skills named in the message get their definition inlined
     * and the rest are listed with their paths.
     */
    private buildAttachedSkillsPromptContext;
    /**
     * Other skills already installed for this run (auto-bundled dependencies,
     * skills from earlier messages), listed so the model can find them by path.
     */
    private getCoInstalledSkillBundles;
    private parseLocalSkillInvocation;
    private buildInstalledSkillPrompt;
    private getInstalledSkillBundleInfoKey;
    private installSkillBundleArtifact;
    private performSkillBundleInstall;
    private extractSkillBundle;
    private getSkillInstallDirectories;
    private hydrateArtifactToPromptBlock;
    private getSafeArtifactName;
    private waitForRepoReady;
    private autoInitializeSession;
    private getResumeRunId;
    private buildSessionSystemPrompt;
    private buildCodexInstructions;
    /**
     * Builds the optional `claudeCode` session meta. Reasoning effort and plugins
     * are independent: effort must reach Claude even when no plugins are set, so
     * it cannot sit behind a plugins guard.
     */
    private buildClaudeCodeSessionMeta;
    private getCloudInteractionOrigin;
    /**
     * Automated, PostHog-branded origins: the Slack app and the Self-driving
     * inbox. These both auto-publish by default and attribute their PRs to
     * "PostHog" rather than the PostHog Code desktop app.
     */
    private isAutomatedOrigin;
    /**
     * Automated-origin cloud runs auto-publish by default, and manual runs
     * auto-publish when the user opted in (Settings → Advanced, sent as
     * autoPublish). Every other run is review-first unless the user explicitly
     * asks, and createPr=false always disables publishing.
     */
    private shouldAutoPublishCloudChanges;
    /**
     * A prewarmed run boots before the user's first message exists, so the
     * --autoPublish flag can't carry the user's choice; the backend persists it
     * into the run's state at warm activation instead. Nothing has been sent to
     * the agent until that first message arrives, so resolving it here still
     * governs the whole conversation: flip the config (so later consumers like
     * buildDetectedPrContext see it) and return the auto-publish cloud
     * instructions to inject into the first prompt as an override.
     */
    private resolveWarmAutoPublishUpgrade;
    private buildDetectedPrContext;
    private buildCloudSystemPrompt;
    private getCurrentGitBranch;
    private syncCloudBranchMetadata;
    private signalTaskComplete;
    private enqueueTaskTerminalEvent;
    private configureEnvironment;
    private buildSlackQuestionRelayResponse;
    private shouldBlockPublishPermission;
    private createCloudClient;
    private relayAgentResponse;
    private relaySlackQuestion;
    private getFirstQuestionMeta;
    private isQuestionMeta;
    private maybeAttachCreatedPr;
    private attachPrIfCreatedThisRun;
    private fetchPrAttribution;
    private ghLoginPromise;
    private fetchGhLogin;
    private cleanupSession;
    private emitRtkSavings;
    private captureCheckpointState;
    private extractHandoffLocalGitState;
    /**
     * Accumulates a settled turn's token usage into the run total and reports it
     * to the backend, merged into `TaskRun.state.token_usage`. Best-effort: a
     * reporting failure must never affect the turn outcome.
     */
    private recordTurnUsage;
    private handleAcpTransportMessage;
    private broadcastTurnComplete;
    private broadcastEvent;
    private flushPreSessionEvents;
    private replayPendingEvents;
    private sendSseEvent;
    /**
     * Relay a permission request (e.g., plan approval) to the connected desktop
     * app via SSE and wait for a response via the `/command` endpoint.
     *
     * The promise waits indefinitely — if SSE is disconnected, the event is
     * buffered by broadcastEvent and replayed when the client reconnects. Session
     * cleanup force-resolves all pending permissions, so there is no leak.
     */
    private relayPermissionToClient;
    private persistPermissionLifecycle;
    private resolvePermission;
}

export { AgentServer, SSE_KEEPALIVE_INTERVAL_MS, UPSTREAM_PROVIDER_FAILURE_MESSAGE, isTurnCompleteNotification };
