feat(team-mode): add team runtime member resolver with tests

This commit is contained in:
YeonGyu-Kim
2026-04-28 10:46:47 +09:00
parent 301e02cdf9
commit a65d54cac3
2 changed files with 320 additions and 0 deletions
@@ -0,0 +1,122 @@
import type { FallbackEntry } from "../../../shared/model-requirements"
import type { DelegatedModelConfig } from "../../../shared/model-resolution-types"
import type { ExecutorContext } from "../../../tools/delegate-task/executor-types"
import type { DelegateTaskArgs } from "../../../tools/delegate-task/types"
import type { Member } from "../types"
import {
buildSystemContent,
resolveCategoryExecution,
resolveSubagentExecution,
} from "./resolve-member-dependencies"
export class TeamMemberResolutionError extends Error {
constructor(public readonly memberName: string, public readonly cause: Error) {
super(`Failed to resolve member '${memberName}': ${cause.message}`)
this.name = "TeamMemberResolutionError"
}
}
export interface ResolvedMember {
memberName: string
agentToUse: string
model: DelegatedModelConfig | undefined
fallbackChain: FallbackEntry[] | undefined
systemContent: string
}
function createBaseDelegateTaskArgs(prompt: string): Pick<DelegateTaskArgs, "description" | "load_skills" | "prompt" | "run_in_background"> {
return {
description: "Resolve team member",
load_skills: [],
prompt,
run_in_background: false,
}
}
function normalizeResolutionError(error: unknown): Error {
return error instanceof Error ? error : new Error(String(error))
}
function resolveSystemContent(input: {
agentToUse: string
categoryPromptAppend?: string
maxPromptTokens?: number
model: DelegatedModelConfig | undefined
}): string {
return buildSystemContent({
agentName: input.agentToUse,
categoryPromptAppend: input.categoryPromptAppend,
maxPromptTokens: input.maxPromptTokens,
model: input.model,
}) ?? ""
}
export async function resolveMember(
member: Member,
ctx: ExecutorContext,
categoryExamples: string,
parentAgent?: string,
): Promise<ResolvedMember> {
try {
if (member.kind === "category") {
const execution = await resolveCategoryExecution(
{
...createBaseDelegateTaskArgs(member.prompt),
category: member.category,
subagent_type: "sisyphus-junior",
},
ctx,
undefined,
undefined,
)
if (execution.error) {
throw new Error(execution.error)
}
return {
memberName: member.name,
agentToUse: execution.agentToUse,
model: execution.categoryModel,
fallbackChain: execution.fallbackChain,
systemContent: resolveSystemContent({
agentToUse: execution.agentToUse,
categoryPromptAppend: execution.categoryPromptAppend,
maxPromptTokens: execution.maxPromptTokens,
model: execution.categoryModel,
}),
}
}
const execution = await resolveSubagentExecution(
{
...createBaseDelegateTaskArgs(member.prompt ?? ""),
subagent_type: member.subagent_type,
},
ctx,
parentAgent,
categoryExamples,
{
allowSisyphusJuniorDirect: true,
allowPrimaryAgentDelegation: true,
},
)
if (execution.error) {
throw new Error(execution.error)
}
return {
memberName: member.name,
agentToUse: execution.agentToUse,
model: execution.categoryModel,
fallbackChain: execution.fallbackChain,
systemContent: resolveSystemContent({
agentToUse: execution.agentToUse,
model: execution.categoryModel,
}),
}
} catch (error) {
throw new TeamMemberResolutionError(member.name, normalizeResolutionError(error))
}
}