import { Command } from "@gajae-code/utils/cli"; import type { Args as ParsedArgs } from "../cli/args"; import { type SessionLifecycleLaunchRequest } from "../sdk/broker/lifecycle"; import { SessionManager } from "../session/session-manager"; export declare function lifecycleArgs(request: SessionLifecycleLaunchRequest, cwd: string, agentDir: string): Promise; /** * How long a session host tolerates the complete absence of a live broker * publication before treating itself as orphaned. Hosts intentionally survive * broker restarts (a replacement broker republishes discovery within seconds), * so this must comfortably exceed a restart window while still bounding the * lifetime of hosts whose broker is gone for good — otherwise every crashed or * torn-down broker leaks a detached multi-hundred-megabyte host forever. */ export declare const SESSION_HOST_BROKER_ABSENCE_GRACE_MS: number; /** * Resolves only once no live broker publication has been observable in * `agentDir` for the full grace window. A reappearing broker (including a * replacement with a different pid) resets the window; an unreadable * publication is not proof of orphanhood but accrues against the same bound. */ export declare function watchSessionHostBrokerLiveness(deps: { agentDir: string; now?: () => number; sleep?: (ms: number) => Promise; readDiscovery?: (agentDir: string) => Promise; graceMs?: number; pollMs?: number; }): Promise; /** * How long a session host that has served at least one client tolerates having * no client attached before treating itself as abandoned. * * This cannot fire during healthy work. "Attached" is the host's own live * socket-subscription count, so a client that is merely idle — an editor * sitting on an open ACP session, a long agent turn with nobody typing — still * holds a socket and resets the window on every poll. Only a client that is * actually gone opens it, and 30 minutes is far longer than any client * reconnect budget (ACP's is seconds), so a crashed-and-restarted client * reattaches long before the window closes. */ export declare const SESSION_HOST_DETACHED_IDLE_GRACE_MS: number; /** * How long a freshly spawned session host waits for its very first client * before treating itself as abandoned. * * A host is ready before its client has finished dialing, so a host that has * never seen an attachment must not be judged by the detached window above. One * hour is orders of magnitude beyond the slowest observed cold start (worktree * preparation, MCP server launch, model-profile application) and beyond any * lifecycle readiness deadline the broker will wait on, so it can only elapse * for a host nobody ever came for. */ export declare const SESSION_HOST_FIRST_ATTACH_GRACE_MS: number; /** * Resolves once the host is provably abandoned: either it has been detached * from every client for a full idle grace, or nobody has come for it at all * for a full first-attach grace. * * `readAttachedClients` reports the host's own live client/socket subscription * count; `undefined` means the SDK endpoint publishes no such evidence — before * startup, after teardown, or when every reader itself fails. That ambiguity is * never instant detachment: it cannot reap on the poll that first sees it, it * can only open a window. Which window depends on what was already observed. A * host never seen attached accrues against the first-attach bound. A host that * was seen attached and has since lost its evidence is in the *more* suspicious * state — a runtime that retracted its registration during teardown looks * exactly like this — so it accrues against the detached idle bound, alongside * an observed count of zero. Every reachable state therefore carries a finite * bound. * * `readWorkInFlight` reports whether the host is running agent work right now. * Work is positive proof a client did come for this host: a prompt can only * arrive over an endpoint a client dialed. Live work therefore restarts both * windows, which is what keeps a mid-prompt host alive whether its count reads * zero or stops being readable at all. That still bounds a host whose SDK * runtime never came up: with no transport it can never receive a prompt, so it * never reports work and its window keeps running from process start. And any * real turn ends, after which the window resumes; live work defers a bound, it * never removes it. */ export declare function watchSessionHostClientAttachment(deps: { readAttachedClients: () => number | undefined; readWorkInFlight?: () => boolean; now?: () => number; sleep?: (ms: number) => Promise; idleGraceMs?: number; firstAttachGraceMs?: number; pollMs?: number; }): Promise; /** Opens lifecycle-authorized history without letting replacement content reach readiness. */ export declare function openLifecycleSessionManager(request: SessionLifecycleLaunchRequest, cwd: string, agentDir: string): Promise<{ parsed: ParsedArgs; sessionManager: SessionManager | undefined; }>; /** * Starts the memory backend a lifecycle session deferred past its readiness * window. * * Deliberately not awaited: the local backend summarises every queued rollout * through the model, so its duration scales with the backlog and would eat the * broker's readiness budget. The session is already published as ready here, so * a failure is a degraded-memory condition, not a startup failure — it is * logged and swallowed instead of surfacing as an unhandled rejection. */ export declare function startMemoryBackendAfterReadiness(start: () => Promise): void; /** Runs the same persisted AgentSession bootstrap used by the production CLI. */ export declare function runSessionHost(timing?: { now?: () => number; sleep?: (ms: number) => Promise; cwd?: string; processIncarnation?: (pid: number) => string | undefined; }): Promise; export type SdkInternalArgv = { action: "broker-internal"; agentDir: string; } | { action: "session-host-internal"; }; /** Parses the exact private argv contracts used by SDK child-process spawns. */ export declare function parseSdkInternalArgv(argv: readonly string[]): SdkInternalArgv; export default class Sdk extends Command { static description: string; static hidden: boolean; static delegateHelp: boolean; static args: { action: import("@gajae-code/utils/cli").ArgDescriptor & { required: false; options: string[]; }; }; static flags: { stdio: import("@gajae-code/utils/cli").FlagDescriptor<"boolean"> & { description: string; }; socket: import("@gajae-code/utils/cli").FlagDescriptor<"string"> & { description: string; }; session: import("@gajae-code/utils/cli").FlagDescriptor<"string"> & { description: string; }; "pending-ceiling": import("@gajae-code/utils/cli").FlagDescriptor<"string"> & { description: string; }; }; run(): Promise; }