- MCP create-backlog-item for natural language Plan/Epic/Task authoring - Worker non-code: optional worktree + per-harness allowlist + doc_review→published - Harness registry: harness_providers/role_harness_routes, WorkerAdapter (minimal|crewai|langgraph|remote-ag-ui), AG-UI POST /api/ag-ui, Settings → Harnesses with Test - Plans tree: backlog.listTree + createPlan/Epic/Task + Start→Convoy, web CRUD without CLI - Fleet: /fleet rollup across workspaces + SSE /api/fleet/events Decision: docs/decisions/2026-08-25-second-brain-os-pivot.md Convoy: .convoys/second-brain-os-v01 Co-authored-by: orchestrator
94 lines
3.2 KiB
TypeScript
94 lines
3.2 KiB
TypeScript
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<string, Partial<HarnessConfig>> = {
|
|
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<string, HarnessConfig> = {
|
|
"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<HarnessConfig> | 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 };
|
|
}
|