refactor(team): move bootstrap prompts into runtime

This commit is contained in:
iliya 2026-04-07 01:30:38 +03:00
parent d4331300c4
commit 0064380160

View file

@ -1194,7 +1194,7 @@ export function buildAddMemberSpawnMessage(
type RuntimeBootstrapMemberSpec = { type RuntimeBootstrapMemberSpec = {
name: string; name: string;
prompt: string; prompt?: string;
cwd?: string; cwd?: string;
model?: string; model?: string;
provider?: TeamProviderId; provider?: TeamProviderId;
@ -1224,6 +1224,7 @@ type RuntimeBootstrapSpec = {
providerId?: TeamProviderId; providerId?: TeamProviderId;
model?: string; model?: string;
effort?: EffortLevel; effort?: EffortLevel;
agentLanguage?: string;
skipPermissions?: boolean; skipPermissions?: boolean;
worktree?: string | null; worktree?: string | null;
extraCliArgs?: string[]; extraCliArgs?: string[];
@ -1239,20 +1240,11 @@ type RuntimeBootstrapSpec = {
}; };
}; };
function memberHasAssignedBoardWork(memberName: string, tasks: TeamTask[]): boolean {
return tasks.some((task) => task.owner === memberName && !task.id.startsWith('_internal'));
}
function buildDeterministicCreateBootstrapSpec( function buildDeterministicCreateBootstrapSpec(
runId: string, runId: string,
request: TeamCreateRequest, request: TeamCreateRequest,
effectiveMembers: TeamCreateRequest['members'] effectiveMembers: TeamCreateRequest['members']
): RuntimeBootstrapSpec { ): RuntimeBootstrapSpec {
const displayName = request.displayName?.trim() || request.teamName;
const leadName =
effectiveMembers.find((member) => member.role?.toLowerCase().includes('lead'))?.name ||
'team-lead';
return { return {
version: 1, version: 1,
runId, runId,
@ -1272,6 +1264,7 @@ function buildDeterministicCreateBootstrapSpec(
...(request.providerId ? { providerId: request.providerId } : {}), ...(request.providerId ? { providerId: request.providerId } : {}),
...(request.model?.trim() ? { model: request.model.trim() } : {}), ...(request.model?.trim() ? { model: request.model.trim() } : {}),
...(request.effort ? { effort: request.effort } : {}), ...(request.effort ? { effort: request.effort } : {}),
agentLanguage: getConfiguredAgentLanguageName(),
...(request.skipPermissions !== undefined ...(request.skipPermissions !== undefined
? { skipPermissions: request.skipPermissions } ? { skipPermissions: request.skipPermissions }
: {}), : {}),
@ -1280,7 +1273,6 @@ function buildDeterministicCreateBootstrapSpec(
}, },
members: effectiveMembers.map((member) => ({ members: effectiveMembers.map((member) => ({
name: member.name, name: member.name,
prompt: buildMemberSpawnPrompt(member, displayName, request.teamName, leadName),
...(member.role?.trim() ? { role: member.role.trim() } : {}), ...(member.role?.trim() ? { role: member.role.trim() } : {}),
...(member.workflow?.trim() ? { workflow: member.workflow.trim() } : {}), ...(member.workflow?.trim() ? { workflow: member.workflow.trim() } : {}),
...(request.cwd ? { cwd: request.cwd } : {}), ...(request.cwd ? { cwd: request.cwd } : {}),
@ -1301,13 +1293,8 @@ function buildDeterministicCreateBootstrapSpec(
function buildDeterministicLaunchBootstrapSpec( function buildDeterministicLaunchBootstrapSpec(
runId: string, runId: string,
request: TeamLaunchRequest, request: TeamLaunchRequest,
effectiveMembers: TeamCreateRequest['members'], effectiveMembers: TeamCreateRequest['members']
tasks: TeamTask[]
): RuntimeBootstrapSpec { ): RuntimeBootstrapSpec {
const leadName =
effectiveMembers.find((member) => member.role?.toLowerCase().includes('lead'))?.name ||
'team-lead';
return { return {
version: 1, version: 1,
runId, runId,
@ -1324,33 +1311,23 @@ function buildDeterministicLaunchBootstrapSpec(
...(request.providerId ? { providerId: request.providerId } : {}), ...(request.providerId ? { providerId: request.providerId } : {}),
...(request.model?.trim() ? { model: request.model.trim() } : {}), ...(request.model?.trim() ? { model: request.model.trim() } : {}),
...(request.effort ? { effort: request.effort } : {}), ...(request.effort ? { effort: request.effort } : {}),
agentLanguage: getConfiguredAgentLanguageName(),
...(request.skipPermissions !== undefined ...(request.skipPermissions !== undefined
? { skipPermissions: request.skipPermissions } ? { skipPermissions: request.skipPermissions }
: {}), : {}),
...(request.worktree ? { worktree: request.worktree } : {}), ...(request.worktree ? { worktree: request.worktree } : {}),
...(request.extraCliArgs ? { extraCliArgs: parseCliArgs(request.extraCliArgs) } : {}), ...(request.extraCliArgs ? { extraCliArgs: parseCliArgs(request.extraCliArgs) } : {}),
}, },
members: effectiveMembers.map((member) => { members: effectiveMembers.map((member) => ({
const reconnectPrompt = shouldUseGeminiStagedLaunch(member.providerId) name: member.name,
? buildGeminiReconnectMemberSpawnPrompt(member, request.teamName, leadName) ...(request.cwd ? { cwd: request.cwd } : {}),
: buildReconnectMemberSpawnPrompt( ...(member.model?.trim() ? { model: member.model.trim() } : {}),
member, ...(member.providerId ? { provider: member.providerId } : {}),
request.teamName, ...(member.effort ? { effort: member.effort } : {}),
leadName, ...(member.role?.trim() ? { role: member.role.trim() } : {}),
memberHasAssignedBoardWork(member.name, tasks) ...(member.workflow?.trim() ? { workflow: member.workflow.trim() } : {}),
); ...(member.role?.trim() ? { description: member.role.trim() } : {}),
return { })),
name: member.name,
prompt: reconnectPrompt,
...(request.cwd ? { cwd: request.cwd } : {}),
...(member.model?.trim() ? { model: member.model.trim() } : {}),
...(member.providerId ? { provider: member.providerId } : {}),
...(member.effort ? { effort: member.effort } : {}),
...(member.role?.trim() ? { role: member.role.trim() } : {}),
...(member.workflow?.trim() ? { workflow: member.workflow.trim() } : {}),
...(member.role?.trim() ? { description: member.role.trim() } : {}),
};
}),
launch: { launch: {
continueOnPartialFailure: true, continueOnPartialFailure: true,
}, },
@ -1638,11 +1615,15 @@ function getSystemLocale(): string {
} }
} }
function getAgentLanguageInstruction(): string { function getConfiguredAgentLanguageName(): string {
const config = ConfigManager.getInstance().getConfig(); const config = ConfigManager.getInstance().getConfig();
const langCode = config.general.agentLanguage || 'system'; const langCode = config.general.agentLanguage || 'system';
const systemLocale = getSystemLocale(); const systemLocale = getSystemLocale();
const languageName = resolveLanguageName(langCode, systemLocale); return resolveLanguageName(langCode, systemLocale);
}
function getAgentLanguageInstruction(): string {
const languageName = getConfiguredAgentLanguageName();
return `IMPORTANT: Communicate in ${languageName}. All messages, summaries, and task descriptions MUST be in ${languageName}.`; return `IMPORTANT: Communicate in ${languageName}. All messages, summaries, and task descriptions MUST be in ${languageName}.`;
} }
@ -4977,8 +4958,7 @@ export class TeamProvisioningService {
const bootstrapSpec = buildDeterministicLaunchBootstrapSpec( const bootstrapSpec = buildDeterministicLaunchBootstrapSpec(
runId, runId,
request, request,
effectiveMemberSpecs, effectiveMemberSpecs
existingTasks
); );
bootstrapSpecPath = await writeDeterministicBootstrapSpecFile(bootstrapSpec); bootstrapSpecPath = await writeDeterministicBootstrapSpecFile(bootstrapSpec);
run.bootstrapSpecPath = bootstrapSpecPath; run.bootstrapSpecPath = bootstrapSpecPath;