ManimCat-show / src /studio-agent /runtime /execution /session-runner-helpers.ts
Bin29's picture
Sync from main: 68df783 feat: support multimodal studio reference images
d47b053
import { createStudioAssistantMessage, createStudioRun } from '../../domain/factories'
import type {
StudioKind,
StudioMessagePart,
StudioRun,
StudioRuntimeTurnPlan,
StudioSession
} from '../../domain/types'
import { buildStudioSubagentPrompt } from '../../prompts/subagent-prompt'
import type { StudioResolvedSkill } from '../tools/tool-runtime-context'
export function buildDraftRun(
session: StudioSession,
inputText: string,
metadata?: Record<string, unknown>
): StudioRun {
return createStudioRun({
sessionId: session.id,
inputText,
activeAgent: session.agentType,
metadata
})
}
export function buildDraftAssistantMessage(session: StudioSession) {
return createStudioAssistantMessage({
sessionId: session.id,
agent: session.agentType
})
}
export function buildSubagentPrompt(input: {
agentType: 'reviewer' | 'designer'
inputText: string
files?: string[]
skillName?: string
skill?: StudioResolvedSkill
studioKind?: StudioKind
}): string {
return buildStudioSubagentPrompt({
agentType: input.agentType,
workflowInput: input.inputText,
files: input.files,
skill: input.skill,
requestedSkillName: input.skillName,
studioKind: input.studioKind
})
}
export function finalizeRunState(input: {
run: StudioRun
outcome: 'continue' | 'stop' | 'compact'
}): StudioRun {
return {
...input.run,
status: input.outcome === 'stop' ? 'failed' : 'completed',
completedAt: new Date().toISOString(),
error: input.outcome === 'stop' ? 'Run stopped after tool failure or rejection' : undefined
}
}
export function failRunState(run: StudioRun, error: string): StudioRun {
return {
...run,
status: 'failed',
completedAt: new Date().toISOString(),
error
}
}
export function cancelRunState(run: StudioRun, reason: string): StudioRun {
return {
...run,
status: 'cancelled',
completedAt: new Date().toISOString(),
error: reason,
}
}
export function extractLatestAssistantText(parts: StudioMessagePart[]): string {
const textPart = [...parts].reverse().find((part) => part.type === 'text')
return textPart?.type === 'text' ? textPart.text : ''
}
export function withResolvedPlan<T extends { plan: StudioRuntimeTurnPlan }>(input: T): T {
return input
}
function readRunStopReason(run: StudioRun): string | undefined {
const autonomy = run.metadata?.autonomy
if (!autonomy || typeof autonomy !== 'object' || Array.isArray(autonomy)) {
return undefined
}
const stopReason = (autonomy as Record<string, unknown>).stopReason
return typeof stopReason === 'string' && stopReason.trim() ? stopReason : undefined
}