import type { Cursor, ExitIntentDTO, IsoTime, LifecycleDTO, ModeDTO, NodeIdDTO, NodeStatusDTO } from './common.js'; /** `POST /v1/nodes` body. Carries the full immediate spawn recipe. */ export interface CreateNodeRequest { kind: string; prompt?: string; profile?: string; mode?: ModeDTO; cwd?: string; /** Display name (tmux window + resume picker). Defaults to the kind. */ name?: string; parent?: NodeIdDTO | null; root?: boolean; /** Worktree branch name, or true for an auto-named managed worktree. */ worktree?: string | boolean; fork_from?: string; model?: string; situational_context?: string; no_kickoff?: boolean; output_schema?: string; /** Spawn AT this exact node id instead of a runtime-minted one — format- * validated and duplicate-rejected server-side (`NodeIdConflictError` → * HTTP 409 `node_id_exists`). See `crtr node new --node-id`. */ node_id?: string; /** Serve this create from the warm pool when a pre-booted spare matches the * request's frozen launch tuple (kind, mode, cwd, profile, model, * situational_context) — answering in milliseconds instead of waiting out a * full engine boot. Only a bare root with no kickoff qualifies; anything the * pool cannot honor (or an empty pool) falls back to an ordinary cold spawn, * so the flag never fails a create, it only ever makes it faster. */ prefer_warm?: boolean; } /** The list/queryable projection of a node — the indexed row columns. */ export interface NodeSummaryDTO { node_id: NodeIdDTO; name: string; kind: string; mode: ModeDTO; lifecycle: LifecycleDTO; status: NodeStatusDTO; cwd: string; host_kind: 'tmux' | 'broker' | null; profile_id: string | null; parent: NodeIdDTO | null; created: IsoTime; intent: ExitIntentDTO; waiting_for: NodeIdDTO | null; pi_pid: number | null; final_report: string | null; finalized_at: IsoTime | null; } /** The spine + subscription edges of a node (absorbs `managers`/`paths` reads). */ export interface NodeEdgesDTO { /** Spine parent (my manager); null for a root. */ parent: NodeIdDTO | null; /** Provenance — who spawned me. */ spawned_by: NodeIdDTO | null; /** Publishers I subscribe to. */ subscribes_to: NodeIdDTO[]; /** Subscribers to my output (my managers). */ subscribers: NodeIdDTO[]; /** Children I spawned. */ children: NodeIdDTO[]; } /** Absolute filesystem paths for a node (absorbs the `paths` read). */ export interface NodePathsDTO { node_dir: string; context_dir: string; reports_dir: string; meta_path: string; inbox_path: string; transcript_path: string; view_socket: string; } /** A node's managed git worktree, if any. */ export interface NodeWorktreeDTO { state: 'open' | 'closed'; path: string; branch: string; repo_root: string; base_ref: string; base_sha: string; created: IsoTime; closed?: IsoTime; } /** The full node view — summary ∪ identity extras ∪ edges ∪ paths. Returned by * `GET /v1/nodes/{id}` and by the create/lifecycle actions that yield a node. */ export interface NodeDetailDTO extends NodeSummaryDTO { description?: string; cycles?: number; /** Approximate context-window token load of the node's live/last session, * used by the orchestrator yield-nudge (`childFollowUp`). Null when unknown * (never launched, or no token accounting yet). */ context_tokens?: number | null; pi_session_id?: string | null; /** Launch-time process-identity fingerprint captured alongside `pi_pid` * (`NodeMeta.pi_pid_identity`), or null. Surfaced so `revive --now`'s * client-side SIGTERM can pass the identity baseline to `recordedPidLiveness` * and refuse to signal a stranger process that reused a dead broker's pid. * Null when the node predates the field or its launch-time capture failed * (fail-open — no baseline means no guard, not a false mismatch). */ pi_pid_identity?: string | null; /** The node's durable model override (`NodeMeta.model_override`), or null when * it runs on the kind/profile default. Surfaced so `node config --model` * can report the resolved model after a patch. */ model_override?: string | null; /** Absolute path to pi's session `.jsonl`, captured at session_start * (`NodeMeta.pi_session_file`). Distinct from `paths.transcript_path` (the * crtr-owned transcript mirror). Consumed by `memory origin` to deref a doc * back to the conversation that authored it. */ pi_session_file?: string | null; edges: NodeEdgesDTO; paths: NodePathsDTO; worktree?: NodeWorktreeDTO | null; /** Present only on a `POST /promote` response — the roadmap/goal facts the * promote primitive returns beyond the node meta (spec §6.2). A plain detail * read omits them. */ roadmap_written?: boolean; roadmap_path?: string; goal_path?: string; } /** `GET /v1/nodes` query filters. */ export interface ListNodesQuery { status?: NodeStatusDTO; kind?: string; mode?: ModeDTO; /** Restrict to the subtree under this node. */ under?: NodeIdDTO; /** Only nodes with a dangling/hanging manager edge. */ hanging?: boolean; } /** `GET /v1/nodes/{id}/snapshot` — the node's reconstructed broker snapshot * (`readNodeSnapshot`): the message log, aggregate stats, and current engine * state, plus the node's registered command set. */ export interface NodeSnapshotDTO { node_id: NodeIdDTO; snapshot: { messages: unknown[]; stats: unknown; state: Record; }; commands: { name: string; description: string; source: string; }[]; captured_at: IsoTime; } /** `GET /v1/nodes/{id}/transcript` query. */ export interface TranscriptQuery { limit?: number; cursor?: Cursor; } /** `GET /v1/nodes/{id}/transcript` result. The reader (`transcriptMarkdown`) * renders the whole conversation as a single markdown document. */ export interface TranscriptDTO { node_id: NodeIdDTO; markdown: string; } /** A canvas artifact under a node (`nodeArtifacts` → `HistoryArtifact`): a * pushed report, a context doc, or the node roadmap. */ export interface ArtifactDTO { /** Stable `:` handle. */ ref: string; /** Artifact source — `report:` | `doc` | `roadmap` | `meta`. */ source: string; ts: IsoTime; title: string; } /** `GET /v1/nodes/{id}/artifacts` query. Narrow to one corpus; absent is the * default report/doc/roadmap set (`inbox` is opt-in only). */ export interface ArtifactsQuery { type?: 'report' | 'doc' | 'roadmap' | 'inbox'; } /** `GET /v1/nodes/{id}/artifacts` result. */ export interface ArtifactListDTO { node_id: NodeIdDTO; artifacts: ArtifactDTO[]; } /** One context root visible to a node — its own dir plus each publisher it * subscribes to (the shared-document roster). */ export interface ContextRootDTO { node_id: NodeIdDTO; label: string; dir: string; /** True for the node's own context root. */ self: boolean; /** Count of context + report files under the root. */ files: number; } /** `GET /v1/nodes/{id}/context` result (the listing; the nvim popup stays local). */ export interface ContextListDTO { node_id: NodeIdDTO; roots: ContextRootDTO[]; }