import type { StudioAssistantMessage, StudioPermissionRequest, StudioProcessorStreamEvent, StudioRun, StudioRuntimeTurnPlan, StudioSession, StudioSessionStore, StudioTaskStore, StudioWorkResultStore, StudioWorkStore } from '../domain/types' import type { StudioPermissionService } from '../permissions/permission-service' import type { StudioToolRegistry } from '../tools/registry' import { createStudioToolCallExecutionEvents } from './tool-call-adapter' import type { StudioResolvedSkill, StudioRuntimeBackedToolContext, StudioSubagentRunRequest, StudioSubagentRunResult } from './tool-runtime-context' import type { CustomApiConfig } from '../../types' interface StudioTurnExecutionOptions { projectId: string session: StudioSession run: StudioRun assistantMessage: StudioAssistantMessage plan: StudioRuntimeTurnPlan registry: StudioToolRegistry eventBus: StudioRuntimeBackedToolContext['eventBus'] permissionService?: StudioPermissionService sessionStore?: StudioSessionStore taskStore?: StudioTaskStore workStore?: StudioWorkStore workResultStore?: StudioWorkResultStore askForConfirmation?: (request: StudioPermissionRequest) => Promise<'once' | 'always' | 'reject'> runSubagent?: (input: StudioSubagentRunRequest) => Promise resolveSkill?: (name: string, session: StudioSession) => Promise setToolMetadata: (callId: string, metadata: { title?: string; metadata?: Record }) => void customApiConfig?: CustomApiConfig } export async function* createStudioTurnExecutionStream( input: StudioTurnExecutionOptions ): AsyncGenerator { const hasAssistantText = Boolean(input.plan.assistantText?.trim()) if (hasAssistantText) { yield { type: 'text-start' } yield { type: 'text-delta', text: input.plan.assistantText ?? '' } yield { type: 'text-end' } } for (const toolCall of input.plan.toolCalls ?? []) { const toolInput = asToolInput(toolCall.input) yield* createStudioToolCallExecutionEvents({ projectId: input.projectId, session: input.session, run: input.run, assistantMessage: input.assistantMessage, toolCallId: toolCall.callId, toolName: toolCall.toolName, toolInput, registry: input.registry, eventBus: input.eventBus, permissionService: input.permissionService, sessionStore: input.sessionStore, taskStore: input.taskStore, workStore: input.workStore, workResultStore: input.workResultStore, askForConfirmation: input.askForConfirmation, runSubagent: input.runSubagent, resolveSkill: input.resolveSkill, setToolMetadata: input.setToolMetadata, customApiConfig: input.customApiConfig, commentary: hasAssistantText ? null : undefined }) } yield { type: 'finish-step' } } function asToolInput(input: unknown): Record { if (input && typeof input === 'object' && !Array.isArray(input)) { return input as Record } return {} }