import type { DaemonAdmitDTO, DaemonRestartDTO, HealthDTO, MigrateStateDTO, MigrateStateRequest, StatusDTO } from './dto/health.js'; import type { BashJobStatusDTO, BashJobStopResultDTO } from './dto/bash-jobs.js'; import type { ArtifactListDTO, ArtifactsQuery, ContextListDTO, CreateNodeRequest, ListNodesQuery, NodeDetailDTO, NodeMessagesPageDTO, NodeMessagesQuery, NodeSessionDTO, NodeSnapshotDTO, NodeSubjectDTO, NodeSummaryDTO, TranscriptDTO, TranscriptQuery } from './dto/nodes.js'; import type { NodeOutcomeResponseDTO, OutcomeDeliveryDTO, RegisterOutcomeDeliveryRequest } from './dto/node-outcomes.js'; import type { NodeEventsQuery } from './dto/node-events.js'; import type { InterruptResultDTO, MessageResultDTO, SendMessageRequest } from './dto/messages.js'; import type { PushReportRequest, PushReportResultDTO, ReportDTO, ReportsQuery, SubmitResultDTO, SubmitResultRequest } from './dto/reports.js'; import type { CloseRequest, CloseResultDTO, PromoteRequest, RelaunchRootResultDTO, ReviveRequest, ReviveResultDTO, WaitRequest, YieldRequest } from './dto/lifecycle.js'; import type { SubscribeRequest, SubscriptionDTO } from './dto/subscriptions.js'; import type { FocusDTO, RegisterFocusRequest, SetFocusPaneRequest } from './dto/focus.js'; import { type ArmCronRequest, type CancelCronQuery, type CronDTO, type CronRunDTO, type CronScopeQuery, type CronShowDTO, type ListCronsQuery, type PokeCronsResult } from './dto/crons.js'; import type { NodeConfigPatch } from './dto/config.js'; import type { AttachEnsureRequest, AttachEnsureResultDTO } from './dto/attach.js'; import type { DeleteProfileRequest, DeleteProfileResultDTO, EnsureProfileRequest, ProfileDTO, ProfilePauseResultDTO, UpdateProfileMetadataRequest } from './dto/profiles.js'; import type { FileEncoding, FileListDTO, FilePeekDTO, FileWriteDTO } from './dto/files.js'; import type { BashRunDTO, BashRunParams } from './dto/bash.js'; import type { MemoryDocCreateRequest, MemoryDocDeletedDTO, MemoryDocDTO, MemoryDocMoveRequest, MemoryDocMovedDTO, MemoryDocRefDTO, MemoryDocUpdateRequest, MemoryHistoryDTO, MemoryHistoryQuery, MemoryListDTO, MemoryListQuery, MemoryScope, MemoryDocSummaryDTO, MemorySearchHitDTO, MemorySearchRequest } from './dto/memory.js'; import type { ChatInventoryDTO, ProspectiveChatInventoryDTO, ProspectiveChatInventoryQuery } from './dto/chat-inventory.js'; import type { CredentialRemovalResultDTO, CredentialResultDTO, InstallCredentialRequest, ModelAuthListDTO, ModelAuthReadinessDTO, ModelAuthReadinessQuery } from './dto/modelauth.js'; import type { CancelReviewRequest, CreateReviewRequest, ListReviewsQuery, ReviewCancelResultDTO, ReviewDocumentBaseDTO, ReviewDTO, ReviewListDTO, ReviewSubmitResultDTO } from './dto/reviews.js'; import type { CreateReviewCommentRequest, EditReviewCommentRequest, ListReviewCommentsQuery, ReadReviewCommentEventsQuery, ReviewCommentActionRequest, ReviewCommentDetailDTO, ReviewCommentEventsDTO, ReviewCommentForkDTO, ReviewCommentListDTO, ReviewCommentMutationDTO, ReviewCommentRangeBatchRequest, ReviewCommentRangeBatchResultDTO } from './dto/review-comments.js'; import type { CancelInboxTicketRequest, CanceledTicketResultDTO, InboxListDTO, InboxPageDTO, InboxPageHistoryDTO, InboxPageResponseDTO, InboxTicketIdDTO, PageFeedbackResolutionDTO, PageResponsesDTO, PageTicketResultDTO, RespondInboxPageRequest } from './dto/inbox.js'; import type { CreateHumanRequestDTO, CreateHumanRequestRequest, HumanRequestDTO, HumanRequestIdDTO, ReplaceHumanRequestRequest, RespondHumanRequestRequest, SettleHumanRequestRequest } from './dto/human-requests.js'; import type { AttentionCountsDTO, AttentionDTO, DashboardDTO, DashboardQuery, HistoryGrepQuery, HistoryGrepResultDTO, HistoryReadQuery, HistoryStatsQuery, HistoryStatsResultDTO, HistoryReadResultDTO, HistorySearchQuery, HistorySearchResultDTO, GraphDTO, PruneRequest, PruneResultDTO, RosterDTO, SnapshotDTO } from './dto/canvas.js'; import type { AbandonWorktreeRequest, AbandonWorktreeResultDTO, CloseWorktreeResultDTO, QuarantinedWorktreeDTO } from './dto/worktree.js'; import type { BrokerExtensionStateDTO, BrokerExecutionRequest, BrokerGeneratedNameRequest, BrokerGeneratedNameResultDTO, BrokerModelCommitRequest, BrokerModelCommitResultDTO, BrokerParkActivityResultDTO, BrokerParkCompleteRequest, BrokerPersonaAckRequest, BrokerPersonaAckResultDTO, BrokerSessionBoundRequest, BrokerSessionBoundResultDTO, BrokerSettleDirective, BrokerSettleRequest, BrokerTelemetryRequest } from './dto/broker-ops.js'; import type { AcknowledgeMailRequest, AcknowledgeMailResultDTO, ClaimMailRequest, ClaimMailResultDTO } from './dto/mail.js'; import type { BrokerFaultInputDTO, BrokerFaultRequest, BrokerFaultResultDTO, BrokerProviderRetryRequest, BrokerProviderRetryResultDTO, BrokerTurnRequest, BrokerTurnResultDTO, NodeFaultClearResultDTO, RecoveryStateDTO } from './dto/recovery.js'; export interface CrtrClientOptions { /** `http(s)://host:port` for a TCP/remote transport. */ baseUrl: string; /** Fetch implementation. The global Web fetch is used unless a caller supplies one. */ fetch?: typeof fetch; /** Extra headers, e.g. `{ authorization: 'Bearer ' }` when the target * crtrd's TCP listener has `CRTRD_TOKEN` set (unix-socket transport is * never checked, and a TCP daemon with no token set ignores this too). */ headers?: Record; /** Retry a cold local connection through this hook once when enabled. */ autostart?: boolean; /** Maximum retries for transient GET, HEAD, and DELETE requests. Defaults to 2. */ maxRetries?: number; /** Per-request timeout in ms (default 30_000). */ timeoutMs?: number; /** Injected daemon-start hook (spec §7.1). Called once on a cold socket when * autostart is on; after it resolves, the client polls `/healthz` and retries * the original request once. Absent → a cold socket throws `daemon_unavailable`. */ onColdSocket?: () => Promise; /** Injected cold-start diagnostic. Called ONLY when the bounded * `/healthz` poll times out after `onColdSocket`, so the caller can attach * operator-useful context (e.g. a bounded tail of `crtrd.log`) to the * `daemon_unavailable` error instead of it staying a bare message. Must * return synchronously and cheaply — it runs on the failure path, not the * happy path. A thrown/undefined result is treated as "no diagnostic". */ coldStartDiagnostic?: () => string | undefined; /** Strict wall-clock window (ms) for local API availability after a cold * socket or interrupted response. Each probe is capped to the remaining * budget. Defaults to `HEALTHZ_POLL_WINDOW_MS`. */ coldStartPollWindowMs?: number; } /** One strict wall-clock availability window shared by local API clients and * daemon management. Each probe gets only the budget remaining at its start. */ export declare function waitForDaemonAvailability({ windowMs, probe, initialError, pollIntervalMs, retry, now, sleep, }: { windowMs: number; probe: (timeoutMs: number) => Promise; initialError?: unknown; pollIntervalMs?: number; retry?: (error: unknown) => boolean; now?: () => number; sleep?: (ms: number) => Promise | void; }): Promise; export interface CrtrRequestOptions { headers?: Record; signal?: AbortSignal; timeout?: number; maxRetries?: number; } export declare class CrtrClient { private readonly baseUrl; private readonly fetch; private readonly headers; private readonly autostart; private readonly timeoutMs; private readonly maxRetries; private readonly localSocketTransport; private readonly onColdSocket?; private readonly coldStartDiagnostic?; private readonly coldStartPollWindowMs; /** Guards against invoking the daemon-start hook more than once per client. */ private coldStartAttempted; constructor(opts: CrtrClientOptions); healthz(): Promise; /** One `/healthz` observation without cold-socket recovery. Availability * waiters own retry policy and pass their remaining wall-clock budget here. */ probeHealthz(timeoutMs: number): Promise; status(): Promise; /** Ask the daemon to replace itself with a successor running the currently * selected runtime generation. Answers before the handover starts, so a * caller living inside a node the handover will tear down still gets a * settled result. */ restartDaemon(): Promise; admitDaemon(): Promise; migrateState(req: MigrateStateRequest): Promise; createNode(req: CreateNodeRequest): Promise; /** List canvas nodes with composable row filters. `include: 'activity'` adds * latest/canonical reports and pending-human counts in the same response. */ listNodes(q?: ListNodesQuery): Promise; getNode(id: string): Promise; /** Read a node outcome, optionally awaiting it for at most 25 seconds. This * is a GET so the client can safely replay it across daemon handover. */ getNodeOutcome(id: string, { waitSeconds }?: { waitSeconds?: number; }): Promise; /** Open the raw server-sent event response for a node. The caller owns SSE * parsing and must consume or cancel the response body. Streams deliberately * have no client wall-clock timeout. */ getNodeEvents(id: string, query?: NodeEventsQuery, options?: Omit): Promise; /** Register or replace an armed target for terminal-outcome delivery. */ registerOutcomeDelivery(id: string, req: RegisterOutcomeDeliveryRequest): Promise; getOutcomeDelivery(id: string): Promise; /** Disarm an unsettled outcome-delivery registration. */ disarmOutcomeDelivery(id: string): Promise; listBashJobs(id: string): Promise; stopBashJob(id: string, jobId: string): Promise; sendMessage(id: string, req: SendMessageRequest): Promise; /** First-class interrupt (the human Esc): cancels pending undelivered * human-send inbox entries, then aborts a live in-flight turn. NEVER * revives a dormant target. */ interruptNode(id: string): Promise; pushReport(id: string, req: PushReportRequest): Promise; submitResult(id: string, req: SubmitResultRequest): Promise; forkNode(id: string): Promise; reviveNode(id: string, req?: ReviveRequest): Promise; relaunchRoot(id: string): Promise; bindBrokerSession(id: string, req: BrokerSessionBoundRequest): Promise; settleBroker(id: string, req: BrokerSettleRequest): Promise; completeBrokerPark(id: string, req: BrokerParkCompleteRequest): Promise; recordBrokerParkActivity(id: string, req: BrokerExecutionRequest): Promise; recordBrokerTelemetry(id: string, req: BrokerTelemetryRequest): Promise; claimNodeMail(id: string, req: ClaimMailRequest): Promise; acknowledgeNodeMail(id: string, req: AcknowledgeMailRequest): Promise; recordBrokerTurn(id: string, req: BrokerTurnRequest): Promise; mutateBrokerProviderRetry(id: string, req: BrokerProviderRetryRequest): Promise; mutateBrokerFault(id: string, req: BrokerFaultRequest): Promise; getBrokerRecovery(id: string, expectedExecutionId: string): Promise; recordNodeFault(id: string, req: BrokerFaultInputDTO): Promise; clearNodeFault(id: string, opts?: { link?: BrokerFaultInputDTO['link']; preserve_episode?: boolean; }): Promise; commitBrokerModel(id: string, req: BrokerModelCommitRequest): Promise; brokerExtensionState(id: string): Promise; commitBrokerGeneratedName(id: string, req: BrokerGeneratedNameRequest): Promise; commitBrokerPersonaAck(id: string, req: BrokerPersonaAckRequest): Promise; closeNode(id: string, req?: CloseRequest): Promise; recycleNode(id: string): Promise; demoteNode(id: string): Promise; promoteNode(id: string, req: PromoteRequest): Promise; yieldNode(id: string, req: YieldRequest): Promise; waitNode(id: string, req: WaitRequest): Promise; patchConfig(id: string, patch: NodeConfigPatch): Promise; /** Land + close the node's managed git worktree (spec §6.2). Server-side * because it interleaves a canvas WRITE with a git land transaction and * crtrd is the repo host (same principle as spawnChild's creation git). */ closeWorktree(id: string): Promise; abandonWorktree(id: string, req: AbandonWorktreeRequest): Promise; listQuarantinedWorktrees(): Promise; subscribe(id: string, req: SubscribeRequest): Promise; listFocuses(): Promise; focusOf(nodeId: string): Promise; focusByPane(pane: string): Promise; registerFocus(req: RegisterFocusRequest): Promise; setFocusPane(focusId: string, req: SetFocusPaneRequest): Promise; closeFocus(focusId: string): Promise; unsubscribe(id: string, target: string): Promise; /** Arm one cron (`POST /v1/crons`) — the server mints the cron_id. */ armCron(req: ArmCronRequest): Promise; /** Crons visible to the caller (`GET /v1/crons`). With `q.profile` that is * that profile's crons plus every global one; omit it only for a * canvas-home-wide provenance read ("which crons did node X arm"). */ listCrons(q?: ListCronsQuery): Promise; /** One cron with its run-log ring (`GET /v1/crons/:cronId`). */ showCron(cronId: string, q?: CronScopeQuery): Promise; /** Pause one cron (`POST /v1/crons/:cronId/pause`) — stops firing, keeps config+history. */ pauseCron(cronId: string, q?: CronScopeQuery): Promise; /** Resume one paused cron (`POST /v1/crons/:cronId/resume`). */ resumeCron(cronId: string, q?: CronScopeQuery): Promise; /** Run one cron NOW, out of band (`POST /v1/crons/:cronId/run`) — synchronous: * resolves with the settled run record after the subprocess closes. Does not * advance the schedule or consume a one-shot; never escalates. */ runCron(cronId: string, q?: CronScopeQuery): Promise; /** Cancel one cron (`DELETE /v1/crons/:cronId`, idempotent). */ cancelCron(cronId: string, q?: CancelCronQuery): Promise; /** Bare eligibility poke (`POST /v1/crons/poke`): re-dues every held active * cron now — "something changed; re-check now". Canvas-wide, label-free, * idempotent, and free when nothing is held. */ pokeCrons(): Promise; ensureAttach(id: string, req?: AttachEnsureRequest): Promise; getReports(id: string, q?: ReportsQuery): Promise; getTranscript(id: string, q?: TranscriptQuery): Promise; getSnapshot(id: string): Promise; /** The node-config subject substrate gates evaluate against. */ nodeSubject(id: string): Promise; getNodeMessages(id: string, q?: NodeMessagesQuery): Promise; /** The node's conversation exactly as it ran — raw `.jsonl` bytes plus the * assembled system prompt. For exports; `getSnapshot` is for renderers. */ getSession(id: string): Promise; /** What a non-terminal chat surface may offer for this node: the chat-capable * slash commands its live engine registered, and the memory documents an * inline `/name` token resolves to. Never revives — a node whose broker is * not live answers `broker_live: false` with empty arrays. */ getChatInventory(id: string): Promise; getProspectiveChatInventory(q?: ProspectiveChatInventoryQuery): Promise; getArtifacts(id: string, q?: ArtifactsQuery): Promise; getContext(id: string): Promise; /** Read an absolute host path (capped, `truncated` when clipped). */ peekFile(path: string, encoding?: FileEncoding, options?: CrtrRequestOptions): Promise; writeFile(path: string, content: string, encoding?: FileEncoding, options?: CrtrRequestOptions): Promise; listFiles(path: string, limit?: number, options?: CrtrRequestOptions): Promise; runBash(params: BashRunParams, options?: CrtrRequestOptions): Promise; /** Resolve an exact canonical `[[name]]` memory-document link to the winning * document's physical origin for the given node — the node's own precedence * chain, not this process's. Pair with `peekFile` to render the document. */ resolveMemoryDoc(name: string, query?: MemoryScope): Promise; listMemoryDocs(query?: MemoryListQuery): Promise>; getMemoryDoc(name: string, query?: MemoryScope & { frontmatter?: boolean; }): Promise; createMemoryDoc(request: MemoryDocCreateRequest): Promise; updateMemoryDoc(name: string, request: MemoryDocUpdateRequest): Promise; deleteMemoryDoc(name: string, query?: MemoryScope): Promise; moveMemoryDoc(name: string, request: MemoryDocMoveRequest): Promise; searchMemoryDocs(request: MemorySearchRequest): Promise>; getMemoryHistory(name: string, query?: MemoryHistoryQuery): Promise; /** Create-or-return by name. Supplied `projects` are shape-checked even when * the profile already exists; their directories are only required to exist * when this call creates the profile. */ ensureProfile(name: string, req?: EnsureProfileRequest): Promise; listProfiles(): Promise; getProfile(name: string): Promise; pauseProfile(name: string): Promise; resumeProfile(name: string): Promise; /** Merge and remove entries in a profile's metadata map. */ updateProfileMetadata(name: string, req: UpdateProfileMetadataRequest): Promise; /** Force-delete or detach one profile by exact id or unique name. */ deleteProfile(name: string, req: DeleteProfileRequest): Promise; listModelAuth(): Promise; getModelAuthReadiness(query?: ModelAuthReadinessQuery): Promise; installCredential(provider: string, req: InstallCredentialRequest): Promise; removeCredential(provider: string): Promise; createReview(req: CreateReviewRequest): Promise; listReviews(query?: ListReviewsQuery): Promise; getReview(reviewId: string): Promise; submitReview(reviewId: string): Promise; cancelReview(reviewId: string, req?: CancelReviewRequest): Promise; getReviewDocumentBase(reviewId: string): Promise; createReviewComment(reviewId: string | undefined, req: CreateReviewCommentRequest): Promise; listReviewComments(reviewId?: string, query?: ListReviewCommentsQuery): Promise; readReviewCommentEvents(reviewId: string, query?: ReadReviewCommentEventsQuery): Promise; updateReviewCommentRanges(reviewId: string, req: ReviewCommentRangeBatchRequest): Promise; getReviewComment(commentId: string): Promise; editReviewComment(commentId: string, req: EditReviewCommentRequest): Promise; resolveReviewComment(commentId: string, req?: ReviewCommentActionRequest): Promise; reopenReviewComment(commentId: string, req?: ReviewCommentActionRequest): Promise; deleteReviewComment(commentId: string, req?: ReviewCommentActionRequest): Promise; forkReviewComment(commentId: string): Promise; /** Pending page/review tickets across every available crouter-owned * humanloop root. */ listHumanInbox(): Promise; /** Read one page ticket by its opaque ticket id (pending, resolved, or canceled). */ getHumanInboxPage(ticketId: InboxTicketIdDTO): Promise; /** All page tickets, oldest first (pending, resolved, or canceled) — * home-wide, or narrowed to one raising node when `nodeId` is given. */ getInboxHistory(nodeId?: string): Promise; /** Submit responses for a page ticket. Single-assignment server-side: a competing * resolution races to `ticket_already_resolved`. */ respondHumanInboxPage(ticketId: InboxTicketIdDTO, request: RespondInboxPageRequest): Promise; /** Autosave partial page work. Omitted slots are permitted in progress updates. */ postInboxProgress(ticketId: InboxTicketIdDTO, responses: PageResponsesDTO): Promise; /** Get the published response for a resolved page ticket. 404 if pending or canceled. */ getInboxResponse(ticketId: InboxTicketIdDTO): Promise; /** Cancel a ticket (terminal response, never deletion). */ cancelHumanInboxTicket(ticketId: InboxTicketIdDTO, request?: CancelInboxTicketRequest): Promise; /** Create one durable human request. The minted `request_id` identifies the * request; inbox presentation has its own ticket id. An unresolvable * `action.name` is rejected before the page is published, leaving no inbox * row behind. */ createHumanRequest(request: CreateHumanRequestRequest): Promise; /** Read one request: its current state, its answer when answered, and the * delivery state of its completion action when it bound one. */ getHumanRequest(requestId: HumanRequestIdDTO): Promise; /** Revise a pending request's page in place. Identity, provenance, and the * frozen action binding are preserved; a settled request refuses. */ replaceHumanRequest(requestId: HumanRequestIdDTO, request: ReplaceHumanRequestRequest): Promise; /** Settle a request `answered` programmatically. Races a human answer to the * same first-writer-wins result. */ respondHumanRequest(requestId: HumanRequestIdDTO, request: RespondHumanRequestRequest): Promise; /** The recipient surface closing a request without answering. */ dismissHumanRequest(requestId: HumanRequestIdDTO, request?: SettleHumanRequestRequest): Promise; /** The requester withdrawing its own request. */ cancelHumanRequest(requestId: HumanRequestIdDTO, request?: SettleHumanRequestRequest): Promise; /** Resolve one page feedback comment — the bound companion's report that it * has been dealt with. `nodeId` names the caller; the daemon refuses any * node but the ticket's companion. Terminal for the comment; appends no * chat turn. */ resolvePageFeedbackComment(ticketId: InboxTicketIdDTO, commentId: string, nodeId: string): Promise; /** Composed client-side from `GET /v1/nodes` + `GET /v1/status` (spec §6.3 — * the dashboard is absorbed into those two reads; there is no single route). * `generated_at` is the client-side capture instant of the composition. */ dashboard(q?: DashboardQuery): Promise; attention(): Promise; /** Per-node pending-ticket counts for a bounded viewer slice. */ attentionCounts(node_ids: string[]): Promise; /** Ranked/filtered content search over the per-cwd episodic corpus * (`crtr canvas history search`). Optional query: ranked when present, * recency browse when omitted. POST-bodied — the query carries arrays and * free text; the whole search executes server-side (spec §6.3). */ historySearch(q: HistorySearchQuery): Promise; /** Required-pattern line-hit search over the per-cwd episodic corpus * (`crtr canvas history grep`). Distinct stable schema from `historySearch` * — POST-bodied for the same reasons. */ historyGrep(q: HistoryGrepQuery): Promise; /** Resolve one `:` history ref to its full body * (`crtr canvas history read`). */ historyRead(q: HistoryReadQuery): Promise; /** Grouped-count projection over the per-cwd episodic corpus * (`crtr canvas history stats`). Same filters as search/grep, aggregate * result instead of a hit page — POST-bodied for the same reasons. */ historyStats(q: HistoryStatsQuery): Promise; /** The machine-readable browser canvas roster (`crtr canvas snapshot`) — * distinct from the per-node `getSnapshot`. */ canvasSnapshot(): Promise; /** The lean, set-based topology roster (`GET /v1/canvas/roster`) — exactly * two indexed queries server-side, no per-row enrichment. The recurring * poll target for attach/browser topology; use `canvasSnapshot` for the * enriched on-demand view. */ canvasRoster(): Promise; /** The lean attach-graph projection: display rows, topology, and focus state * in one daemon-owned read rather than the full node-summary list. */ canvasGraph(): Promise; prune(req: PruneRequest): Promise; /** Raw request for routes not yet method-wrapped. Applies the same * autostart + retry + error-mapping semantics. */ request(method: string, path: string, body?: unknown, opts?: CrtrRequestOptions): Promise; /** The unparsed request: cold-socket and interrupted-response recovery, plus * the §7 retry policy (connection errors and 429/5xx on GET/HEAD/DELETE * only — POST/PATCH are never replayed once a request has actually been * sent). No JSON parse; every wrapper goes through here. */ private send; private nodePath; /** Validate a background job id before route construction. Job ids arrive * from the daemon's file-backed roster and must remain one path segment. */ private jobPath; /** Validate a cron id before route construction — `routes.ts` interpolates * it raw, so a value carrying `/`, whitespace or `?` would corrupt the * request line rather than 404 cleanly. Mirrors `nodePath`. */ private cronPath; /** Validate a request id before route construction. Requests use the daemon's * node-id-shaped identifiers, while inbox presentation uses a separate ticket * id. A malformed request id is a server-rejectable request. */ private requestPath; /** Validate an opaque inbox ticket id before route construction. A local * shape violation is a caller bug, not a server-rejectable request — throws * `TypeError` (matching the existing safe-segment discipline of a local * precondition, distinct from `nodePath`'s `ApiError` because that one IS a * request the server could plausibly receive and reject itself). */ private ticketId; /** Validate a review id before route construction (D-A6). Reviews are minted * and addressed like node ids, but arrive from agent argv, so a malformed * one is a plausible request the server would also reject — `ApiError`, * not `TypeError`, matching `nodePath`. */ private reviewPath; /** Validate a comment id before route construction (D-A6). Comment ids are * daemon-minted 32-char lowercase hex, but — like `reviewPath` — arrive from * agent argv, so a bad one is a plausible request the server would also * reject, not a caller-bug `TypeError` like `ticketId`. */ private commentPath; /** The one fetch path (§1). Resolves as soon as headers arrive — the body * stays an unread `ReadableStream` on the returned `Response`, so a caller * that wants to stream (SSE, later) never waits on a buffered body. */ private transport; private retainRequestLifetime; private isColdSocketError; /** A connection torn down MID-request (Node's "socket hang up" / a broken * pipe). It establishes only that the response was interrupted, not why. */ private isInterruptedSocketError; /** Wait for the local API after an interrupted response. GET/HEAD can retry * because they are idempotent. A mutation may already have been applied, so * it never replays. */ private rideOutInterruptedRequest; private awaitAvailability; /** Optionally start the daemon, then observe availability before retrying the * request. Waiting is independent from permission to spawn: externally * managed daemons still get the same bounded readiness window. */ private handleColdSocket; } export declare function safeColdStartDiagnostic(hook: (() => string | undefined) | undefined): string | undefined;