File size: 4,519 Bytes
abcf568
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import { createStudioOpenAIToolLoop } from '../../../orchestration/openai-tool-loop/controller'
import { createStudioTurnExecutionStream } from '../tool-execution-stream'
import { readRunElapsedMs } from '../../../observability/plot-studio-timing'
import type { CustomApiConfig } from '../../../../types'
import type { StudioToolChoice, StudioRuntimeTurnPlan } from '../../../domain/types'
import type { StudioPreparedRunContext, StudioPreparedRunExecution, StudioSessionRunnerDependencies } from './dependency-center'

export function createResolvedPlanExecution(
  deps: StudioSessionRunnerDependencies,
  input: {
    prepared: StudioPreparedRunContext
    plan: StudioRuntimeTurnPlan
    customApiConfig?: CustomApiConfig
    toolChoice?: StudioToolChoice
    abortSignal: AbortSignal
  },
): StudioPreparedRunExecution {
  return {
    events: createStudioTurnExecutionStream({
      projectId: input.prepared.input.projectId,
      session: input.prepared.input.session,
      run: input.prepared.run,
      assistantMessage: input.prepared.assistantMessage,
      plan: input.plan,
      registry: deps.registry,
      eventBus: input.prepared.eventBus,
      messageStore: deps.messageStore,
      partStore: deps.partStore,
      sessionStore: deps.sessionStore,
      taskStore: deps.taskStore,
      workStore: deps.workStore,
      workResultStore: deps.workResultStore,
      runSubagent: (request) => deps.runSubagent({
        ...request,
        customApiConfig: input.customApiConfig,
        toolChoice: input.toolChoice
      }),
      resolveSkill: deps.resolveSkill,
      listSkills: deps.listSkills,
      listSkillSummaries: deps.listSkillSummaries,
      recordSkillUsage: deps.recordSkillUsage,
      setToolMetadata: (callId, metadata) => {
        void deps.processor.applyToolMetadata({
          assistantMessage: input.prepared.assistantMessage,
          callId,
          title: metadata.title,
          metadata: metadata.metadata
        })
      },
      customApiConfig: input.customApiConfig,
      abortSignal: input.abortSignal,
    })
  }
}

export function createAgentLoopExecution(
  deps: StudioSessionRunnerDependencies,
  input: {
    prepared: StudioPreparedRunContext
    customApiConfig: CustomApiConfig
    toolChoice?: StudioToolChoice
    abortSignal: AbortSignal
  },
): StudioPreparedRunExecution {
  return {
    startLog: {
      event: 'loop.started',
      payload: {
        sessionId: input.prepared.input.session.id,
        runId: input.prepared.run.id,
        model: input.customApiConfig.model,
        toolChoice: input.toolChoice ?? null,
        runElapsedMs: readRunElapsedMs(input.prepared.run),
      }
    },
    events: createStudioOpenAIToolLoop({
      projectId: input.prepared.input.projectId,
      session: input.prepared.input.session,
      run: input.prepared.run,
      assistantMessage: input.prepared.assistantMessage,
      inputText: input.prepared.input.inputText,
      messageStore: deps.messageStore,
      registry: deps.registry,
      eventBus: input.prepared.eventBus,
      partStore: deps.partStore,
      sessionStore: deps.sessionStore,
      taskStore: deps.taskStore,
      workStore: deps.workStore,
      workResultStore: deps.workResultStore,
      workContext: input.prepared.workContext,
      runSubagent: (request) => deps.runSubagent({
        ...request,
        customApiConfig: input.customApiConfig,
        toolChoice: input.toolChoice
      }),
      resolveSkill: deps.resolveSkill,
      listSkills: deps.listSkills,
      listSkillSummaries: deps.listSkillSummaries,
      recordSkillUsage: deps.recordSkillUsage,
      createAssistantMessage: () => deps.createAssistantMessage(input.prepared.input.session, input.prepared.run.id),
      setToolMetadata: (assistantMessage, callId, metadata) => {
        void deps.processor.applyToolMetadata({
          assistantMessage,
          callId,
          title: metadata.title,
          metadata: metadata.metadata
        })
      },
      customApiConfig: input.customApiConfig,
      toolChoice: input.toolChoice,
      abortSignal: input.abortSignal,
      onCheckpoint: async (patch) => {
        const nextRun = deps.runStore
          ? await deps.runStore.update(input.prepared.run.id, patch) ?? { ...input.prepared.run, ...patch }
          : { ...input.prepared.run, ...patch }
        input.prepared.run = nextRun
        input.prepared.eventBus.publish({
          type: 'run_updated',
          run: nextRun
        })
      }
    })
  }
}