/** * Single-owner host-neutral TurnRequest projection (#526 / standards-3). * Collapses common principal, cwd, runDirectory, model, engine, continuation, * and correlationId assembly across all public roles. */ import type { DurablePrincipal, MethodBinding, RoleTurnActivation, RoleTurnModelConfig, RoleTurnRequest, } from "../host-contracts.ts"; import { pickEngineAxis } from "../package-resources/engine-material.ts"; import type { SeatModelConfig } from "./config.ts"; import type { PublicThinkingLevel } from "./registry.ts"; /** Structural model shape shared by the seam so seat/env sources fit. */ export type ResumeModelConfig = { readonly provider: string; readonly model: string; readonly thinking?: PublicThinkingLevel; }; export type RoleTurnRequestProjectionOptions = { packageRoot: string; home: string; agentDir: string; model?: SeatModelConfig; engine?: string; /** Labor-engine model id (#883); projected onto the turn when present. */ engineModel?: string; timeoutMs?: number; correlationId?: string; continuation: RoleTurnRequest["continuation"]; /** #833 resume-with-message court attempt. */ courtAttemptId?: string; /** #537 public-invocation scope (one ak-role call). */ invocationScopeId?: string; /** Station child role run (#840): omit automatic navigator attendance. */ stationChild?: boolean; /** * Optional host-turn cwd override. Durable admitted projectRoot stays the * identity source; Reviewer fresh-copy sandboxes (explicit --lens, dual-lens * legs, resume) inject the ephemeral worktree here (#946 统一新副本). */ cwd?: string; }; export type AdmittedTurnInvocation = { principal?: DurablePrincipal; projectRoot?: string; repoRoot?: string; cwd?: string; runDirectory: string; /** Recorded model at admission (provenance); turn model comes from options.model. */ model?: ResumeModelConfig; }; export function projectRoleTurnRequest( admitted: AdmittedTurnInvocation, roleDetails: { activation: RoleTurnActivation; methods?: readonly MethodBinding[]; }, options: RoleTurnRequestProjectionOptions, ): RoleTurnRequest { const cwd = options.cwd ?? admitted.projectRoot ?? admitted.repoRoot ?? admitted.cwd; if (cwd === undefined) throw new Error("admitted invocation missing working directory"); if (admitted.principal === undefined) throw new Error("admitted invocation missing principal"); // #617 DK-3: turn model is the live seat/env model only — never the admitted // birth model. Resume and new legs share this projection. return { principal: admitted.principal, activation: roleDetails.activation, methods: roleDetails.methods ?? [], continuation: options.continuation, ...(options.model === undefined ? {} : { model: options.model }), ...pickEngineAxis(options), cwd, home: options.home, agentDir: options.agentDir, runDirectory: admitted.runDirectory, ...(options.correlationId === undefined || options.correlationId.trim() === "" ? {} : { correlationId: options.correlationId }), ...(options.timeoutMs === undefined ? {} : { timeoutMs: options.timeoutMs }), ...(options.courtAttemptId === undefined || options.courtAttemptId.length === 0 ? {} : { courtAttemptId: options.courtAttemptId }), ...(options.invocationScopeId === undefined || options.invocationScopeId.length === 0 ? {} : { invocationScopeId: options.invocationScopeId }), ...(options.stationChild === undefined ? {} : { stationChild: options.stationChild }), }; }