import { StudioRunProcessor } from '../run-processor' import type { StudioAssistantMessage, StudioRun, StudioSession, StudioRuntimeTurnPlan, StudioToolChoice, } from '../../../domain/types' import type { CustomApiConfig } from '../../../../types' import type { StudioSubagentRunRequest, StudioSubagentRunResult } from '../../tools/tool-runtime-context' import type { StudioBackgroundRunHandle, StudioPreparedRunContext, StudioRunRequestInput, StudioSessionRunnerDependencies, StudioSessionRunnerOptions } from './dependency-center' import { createAssistantMessage, createRun } from './factory' import { buildWorkContext, prepareRun } from './preparer' import { routePreparedRun } from './router' import { createResolvedPlanExecution } from './execution-factories' import { executePreparedStream } from './execution-manager' import { createDependencyCenter } from './dependency-center' import { runSubagent as executeSubagent } from './subagent-manager' export class StudioSessionRunner { private readonly deps: StudioSessionRunnerDependencies constructor(options: StudioSessionRunnerOptions) { const processor = new StudioRunProcessor({ messageStore: options.messageStore, partStore: options.partStore }) this.deps = createDependencyCenter(options, { processor, createRun: (session, inputText, metadata) => createRun(session, inputText, metadata), createAssistantMessage: (session) => createAssistantMessage({ messageStore: options.messageStore }, session), buildWorkContext: (input) => buildWorkContext({ workStore: options.workStore, workResultStore: options.workResultStore, taskStore: options.taskStore, sessionEventStore: options.sessionEventStore }, input), runSubagent: (input) => this.runSubagent(input) }) } async createAssistantMessage(session: StudioSession): Promise { return createAssistantMessage(this.deps, session) } createRun(session: StudioSession, inputText: string, metadata?: Record): StudioRun { return createRun(session, inputText, metadata) } async run(input: StudioRunRequestInput): Promise { const handle = await this.startBackgroundRun(input) return handle.completion } async startBackgroundRun(input: StudioRunRequestInput): Promise { const prepared = await prepareRun(this.deps, input) const abortController = new AbortController() return { run: prepared.run, assistantMessage: prepared.assistantMessage, abort: (reason?: string) => abortController.abort(reason ?? 'Run cancelled'), completion: this.executePreparedRun(prepared, abortController.signal) } } async runWithPlan(input: { projectId: string session: StudioSession inputText: string plan: StudioRuntimeTurnPlan customApiConfig?: CustomApiConfig toolChoice?: StudioToolChoice }): Promise { const prepared = await prepareRun(this.deps, input) const abortController = new AbortController() return executePreparedStream(this.deps, prepared, createResolvedPlanExecution(this.deps, { prepared, plan: input.plan, customApiConfig: input.customApiConfig, toolChoice: input.toolChoice, abortSignal: abortController.signal, }), abortController.signal) } async runSubagent(input: StudioSubagentRunRequest): Promise { return executeSubagent(this.deps, input, (request) => this.run(request)) } private async executePreparedRun(prepared: StudioPreparedRunContext, abortSignal: AbortSignal) { return routePreparedRun(this.deps, prepared, abortSignal) } }