{"version":3,"file":"cockpitContainer.cjs","names":[],"sources":["../../src/schemas/cockpitContainer.ts"],"sourcesContent":["/**\n * Cockpit container harness contract.\n *\n * The sandbox harness next door provisions a container, runs one interactive\n * launch inside it, and reports the exit code. This is the other shape: a\n * detached container that outlives the call, holding the cockpit hub and every\n * session it goes on to spawn.\n *\n * The difference is worth its own contract rather than a flag. `launchSandbox`\n * returns `Promise<number>`, which cannot express \"it is running, here is the\n * handle\", and its credential broker is torn down as soon as that promise\n * settles. A detached cockpit needs both to outlive the call.\n *\n * Core and the cockpit resolve this dynamically from the selected composition,\n * exactly as they resolve the sandbox harness, so neither depends on a concrete\n * container technology.\n */\n\n/** Exports subpath a layer package declares when it can host the cockpit. */\nexport const COCKPIT_HARNESS_EXPORT_SUBPATH = './cockpit-harness';\n\n/** One host directory the cockpit may work in, bind-mounted at its own path. */\nexport interface CockpitWorkspace {\n  /**\n   * Absolute host path, mounted at the identical path inside the container so\n   * every absolute path the cockpit already holds keeps resolving.\n   */\n  path: string;\n}\n\nexport interface CockpitContainerRequest {\n  /**\n   * Directories the cockpit may create sessions in. This list is the boundary:\n   * a hub inside the container cannot reach a path that is not here, which is\n   * what makes \"sessions only start in mounted directories\" true by\n   * construction rather than by a check that can be weakened later.\n   */\n  workspaces: readonly CockpitWorkspace[];\n  /** Loopback port the cockpit is published on, and the port it binds inside. */\n  port: number;\n  /** Host environment the provider filters before any of it enters the container. */\n  environment: NodeJS.ProcessEnv;\n  /** Receives one human-readable line per provisioning decision, including image builds. */\n  onProgress?: (message: string) => void;\n}\n\nexport interface CockpitContainerHandle {\n  /** Engine-assigned id, recorded on the host so an orphan can be reaped later. */\n  readonly containerId: string;\n  /** Stops the container and releases everything provisioned alongside it. */\n  stop(): Promise<void>;\n  /**\n   * Whether the container is still running.\n   *\n   * The supervising process has no server of its own once it has handed over,\n   * so this is what it watches: a container that died has to end the supervisor\n   * with it, rather than leaving a process that owns nothing.\n   */\n  alive(): Promise<boolean>;\n}\n\nexport type CockpitContainerStart = { ok: true; handle: CockpitContainerHandle } | { ok: false; error: string };\n\nexport interface CockpitContainerHarnessModule {\n  /**\n   * Builds the image if it is missing, starts the container detached, and\n   * returns once the cockpit inside is answering.\n   */\n  startCockpitContainer(request: CockpitContainerRequest): Promise<CockpitContainerStart>;\n  /**\n   * Stops a container this harness started in an earlier process, named by id.\n   * Resolves true when one was found and stopped.\n   */\n  reapCockpitContainer(containerId: string): Promise<boolean>;\n}\n\n/** Narrowing guard for a dynamically imported cockpit harness entry. */\nexport function isCockpitContainerHarnessModule(value: unknown): value is CockpitContainerHarnessModule {\n  if (typeof value !== 'object' || value === null) return false;\n  const candidate = value as Partial<CockpitContainerHarnessModule>;\n  return typeof candidate.startCockpitContainer === 'function' && typeof candidate.reapCockpitContainer === 'function';\n}\n"],"mappings":"AA6EA,SAAgB,EAAgC,EAAwD,CACtG,GAAI,OAAO,GAAU,WAAY,EAAgB,MAAO,GACxD,IAAM,EAAY,EAClB,OAAO,OAAO,EAAU,uBAA0B,YAAc,OAAO,EAAU,sBAAyB,UAC5G"}