import { ALLOWED_COMMANDS } from "@tasks/shared/worker"; import type { HarnessType } from "@tasks/shared/worker"; export type HarnessConfig = { alias: string; harnessType: HarnessType; needsWorktree: boolean; allowedCommands: readonly string[] | null; endpointUrl?: string | null; authEnvVar?: string | null; }; const DOC_WRITER: HarnessConfig = { alias: "doc-writer", harnessType: "minimal", needsWorktree: false, allowedCommands: [], }; const DEFAULT: HarnessConfig = { alias: "minimal", harnessType: "minimal", needsWorktree: true, allowedCommands: null, }; const HARNESS_DEFAULTS: Record> = { minimal: { harnessType: "minimal", needsWorktree: true, allowedCommands: null }, crewai: { harnessType: "crewai", needsWorktree: true, allowedCommands: null }, langgraph: { harnessType: "langgraph", needsWorktree: true, allowedCommands: null }, "remote-ag-ui": { harnessType: "remote-ag-ui", needsWorktree: false, allowedCommands: [] }, }; const HARNESS_BY_ALIAS: Record = { "doc-writer": DOC_WRITER, minimal: DEFAULT, default: DEFAULT, }; function configForAlias(alias: string): HarnessConfig { if (HARNESS_BY_ALIAS[alias]) return HARNESS_BY_ALIAS[alias]!; const def = HARNESS_DEFAULTS[alias] as Partial | undefined; if (def?.harnessType) { return { alias, harnessType: def.harnessType, needsWorktree: def.needsWorktree ?? true, allowedCommands: def.allowedCommands ?? null, }; } return { alias, harnessType: "minimal", needsWorktree: true, allowedCommands: null }; } /** * Resolve harness config for a job. Brief 3 adds harness_providers + remote-ag-ui. * - If job carries `harnessAlias` use it (from orchestrator or DB route). * - Else if roleId itself is a harness alias use it. * - Else fallback to minimal. */ export function resolveHarnessForJob(job: { roleId: string; harnessAlias?: string | null; harnessType?: string | null; endpointUrl?: string | null; authEnvVar?: string | null; }): HarnessConfig { const alias = job.harnessAlias ?? (HARNESS_BY_ALIAS[job.roleId] ? job.roleId : null); if (alias) { const base = configForAlias(alias); return { ...base, ...(job.harnessType ? { harnessType: job.harnessType as HarnessType } : {}), ...(job.endpointUrl !== undefined ? { endpointUrl: job.endpointUrl } : {}), ...(job.authEnvVar !== undefined ? { authEnvVar: job.authEnvVar } : {}), }; } if (job.roleId.includes("doc")) return DOC_WRITER; return DEFAULT; } export function allowedCommandsForHarness(harness: HarnessConfig): readonly string[] | null { return harness.allowedCommands === null ? ALLOWED_COMMANDS : harness.allowedCommands; } /** * Executor registry — minimal adapter delegates to MinimalSession; remote adapters * could call AG-UI endpoint. For brief 3 all adapters share the same local * MinimalSession implementation but are differentiated by harnessType for * observability and future extension. */ export function getHarnessExecutor(alias: string): { id: string; harnessType: HarnessType } { const cfg = configForAlias(alias); return { id: cfg.alias, harnessType: cfg.harnessType }; }