- 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
53 lines
2 KiB
TypeScript
53 lines
2 KiB
TypeScript
import { and, eq } from "drizzle-orm";
|
|
import type { db as dbInstance } from "@tasks/database";
|
|
import { harnessProviders, roleHarnessRoutes } from "@tasks/database/schema";
|
|
import { resolveHarnessForRole } from "@tasks/shared/worker/executor";
|
|
|
|
type Db = typeof dbInstance;
|
|
|
|
export async function resolveHarnessForRoleDb(
|
|
db: Db,
|
|
workspaceId: string,
|
|
roleId: string,
|
|
overrideAlias?: string | null,
|
|
): Promise<{ alias: string; harnessType: string; endpointUrl: string | null; authEnvVar: string | null }> {
|
|
if (overrideAlias) {
|
|
const [row] = await db
|
|
.select()
|
|
.from(harnessProviders)
|
|
.where(and(eq(harnessProviders.workspaceId, workspaceId), eq(harnessProviders.alias, overrideAlias)))
|
|
.limit(1);
|
|
if (row && row.enabled) {
|
|
return { alias: row.alias, harnessType: row.harnessType, endpointUrl: row.endpointUrl, authEnvVar: row.authEnvVar };
|
|
}
|
|
}
|
|
const providers = await db.select().from(harnessProviders).where(eq(harnessProviders.workspaceId, workspaceId));
|
|
const routes = await db.select().from(roleHarnessRoutes).where(eq(roleHarnessRoutes.workspaceId, workspaceId));
|
|
// map to shared types
|
|
const mappedProviders = providers.map((p) => ({
|
|
id: p.id,
|
|
workspaceId: p.workspaceId,
|
|
alias: p.alias,
|
|
displayName: p.displayName,
|
|
harnessType: p.harnessType as "minimal" | "crewai" | "langgraph" | "remote-ag-ui",
|
|
endpointUrl: p.endpointUrl,
|
|
authEnvVar: p.authEnvVar,
|
|
config: p.config,
|
|
enabled: p.enabled,
|
|
}));
|
|
const mappedRoutes = routes.map((r) => ({
|
|
id: r.id,
|
|
workspaceId: r.workspaceId,
|
|
roleId: r.roleId,
|
|
harnessProviderId: r.harnessProviderId,
|
|
enabled: r.enabled,
|
|
sortOrder: r.sortOrder,
|
|
}));
|
|
const result = resolveHarnessForRole({ roleId, providers: mappedProviders, routes: mappedRoutes });
|
|
return {
|
|
alias: result.harness.alias,
|
|
harnessType: result.harness.harnessType,
|
|
endpointUrl: result.harness.endpointUrl ?? null,
|
|
authEnvVar: result.harness.authEnvVar ?? null,
|
|
};
|
|
}
|