@lota-sdk/core 0.4.13 → 0.4.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. package/package.json +4 -4
  2. package/src/ai/embedding-cache.ts +17 -11
  3. package/src/ai-gateway/ai-gateway.ts +164 -94
  4. package/src/ai-gateway/index.ts +4 -1
  5. package/src/config/agent-defaults.ts +2 -2
  6. package/src/config/agent-types.ts +1 -1
  7. package/src/config/constants.ts +1 -1
  8. package/src/create-runtime.ts +259 -200
  9. package/src/db/cursor-pagination.ts +2 -9
  10. package/src/db/memory-store.ts +194 -175
  11. package/src/db/memory.ts +125 -71
  12. package/src/db/schema-fingerprint.ts +5 -4
  13. package/src/db/service-normalization.ts +4 -3
  14. package/src/db/service.ts +3 -2
  15. package/src/db/startup.ts +15 -16
  16. package/src/effect/errors.ts +161 -21
  17. package/src/effect/index.ts +0 -1
  18. package/src/embeddings/provider.ts +15 -7
  19. package/src/queues/autonomous-job.queue.ts +10 -22
  20. package/src/queues/delayed-node-promotion.queue.ts +8 -14
  21. package/src/queues/document-processor.queue.ts +13 -4
  22. package/src/queues/memory-consolidation.queue.ts +26 -14
  23. package/src/queues/plan-agent-heartbeat.queue.ts +48 -31
  24. package/src/queues/plan-scheduler.queue.ts +37 -15
  25. package/src/queues/queue-factory.ts +59 -35
  26. package/src/queues/standalone-worker.ts +3 -2
  27. package/src/redis/connection.ts +10 -3
  28. package/src/redis/org-memory-lock.ts +1 -1
  29. package/src/redis/redis-lease-lock.ts +5 -5
  30. package/src/redis/stream-context.ts +1 -1
  31. package/src/runtime/chat-message.ts +64 -1
  32. package/src/runtime/chat-run-orchestration.ts +33 -20
  33. package/src/runtime/context-compaction/context-compaction-runtime.ts +14 -7
  34. package/src/runtime/context-compaction/context-compaction.ts +78 -66
  35. package/src/runtime/domain-layer.ts +19 -13
  36. package/src/runtime/execution-plan.ts +7 -3
  37. package/src/runtime/memory/memory-block.ts +3 -9
  38. package/src/runtime/memory/memory-scope.ts +3 -1
  39. package/src/runtime/plugin-resolution.ts +2 -1
  40. package/src/runtime/post-turn-side-effects.ts +6 -5
  41. package/src/runtime/retrieval-adapters.ts +8 -20
  42. package/src/runtime/runtime-config.ts +3 -9
  43. package/src/runtime/runtime-extensions.ts +2 -4
  44. package/src/runtime/runtime-lifecycle.ts +56 -16
  45. package/src/runtime/runtime-services.ts +180 -102
  46. package/src/runtime/runtime-worker-registry.ts +3 -1
  47. package/src/runtime/social-chat/social-chat-agent-runner.ts +1 -1
  48. package/src/runtime/social-chat/social-chat-history.ts +21 -18
  49. package/src/runtime/social-chat/social-chat.ts +356 -223
  50. package/src/runtime/specialist-runner.ts +3 -1
  51. package/src/runtime/team-consultation/team-consultation-orchestrator.ts +3 -2
  52. package/src/runtime/thread-turn-context.ts +142 -102
  53. package/src/runtime/turn-lifecycle.ts +15 -46
  54. package/src/services/agent-activity.service.ts +1 -1
  55. package/src/services/agent-executor.service.ts +107 -77
  56. package/src/services/autonomous-job.service.ts +354 -293
  57. package/src/services/background-work.service.ts +3 -3
  58. package/src/services/context-compaction.service.ts +7 -2
  59. package/src/services/document-chunk.service.ts +50 -32
  60. package/src/services/execution-plan/execution-plan-schedule.ts +5 -3
  61. package/src/services/execution-plan/execution-plan.service.ts +162 -179
  62. package/src/services/feedback-loop.service.ts +5 -4
  63. package/src/services/graph-full-routing.ts +37 -36
  64. package/src/services/institutional-memory.service.ts +28 -30
  65. package/src/services/learned-skill.service.ts +107 -72
  66. package/src/services/memory/memory-errors.ts +4 -23
  67. package/src/services/memory/memory-org-memory.ts +10 -5
  68. package/src/services/memory/memory-rerank.ts +18 -6
  69. package/src/services/memory/memory.service.ts +170 -111
  70. package/src/services/memory/rerank.service.ts +29 -20
  71. package/src/services/organization-member.service.ts +1 -1
  72. package/src/services/organization.service.ts +69 -75
  73. package/src/services/ownership-dispatcher.service.ts +40 -39
  74. package/src/services/plan/plan-agent-heartbeat.service.ts +22 -24
  75. package/src/services/plan/plan-agent-query.service.ts +39 -31
  76. package/src/services/plan/plan-completion-side-effects.ts +13 -17
  77. package/src/services/plan/plan-coordination.service.ts +2 -1
  78. package/src/services/plan/plan-cycle.service.ts +6 -5
  79. package/src/services/plan/plan-deadline.service.ts +57 -54
  80. package/src/services/plan/plan-event-delivery.service.ts +5 -4
  81. package/src/services/plan/plan-executor-graph.ts +18 -15
  82. package/src/services/plan/plan-executor.service.ts +235 -262
  83. package/src/services/plan/plan-run.service.ts +169 -93
  84. package/src/services/plan/plan-scheduler.service.ts +192 -202
  85. package/src/services/plan/plan-template.service.ts +1 -1
  86. package/src/services/plan/plan-transaction-events.ts +1 -1
  87. package/src/services/plan/plan-workspace.service.ts +23 -14
  88. package/src/services/plugin-executor.service.ts +5 -9
  89. package/src/services/queue-job.service.ts +117 -59
  90. package/src/services/recent-activity-title.service.ts +13 -12
  91. package/src/services/recent-activity.service.ts +6 -1
  92. package/src/services/social-chat-history.service.ts +29 -25
  93. package/src/services/system-executor.service.ts +5 -9
  94. package/src/services/thread/thread-active-run.ts +2 -2
  95. package/src/services/thread/thread-listing.ts +61 -57
  96. package/src/services/thread/thread-memory-block.ts +73 -48
  97. package/src/services/thread/thread-message.service.ts +76 -65
  98. package/src/services/thread/thread-record-store.ts +8 -8
  99. package/src/services/thread/thread-title.service.ts +10 -4
  100. package/src/services/thread/thread-turn-execution.ts +43 -45
  101. package/src/services/thread/thread-turn-preparation.service.ts +257 -135
  102. package/src/services/thread/thread-turn-streaming.ts +83 -92
  103. package/src/services/thread/thread-turn.ts +18 -16
  104. package/src/services/thread/thread.service.ts +135 -100
  105. package/src/services/user.service.ts +45 -48
  106. package/src/storage/attachment-parser.ts +6 -2
  107. package/src/storage/attachment-storage.service.ts +5 -6
  108. package/src/storage/generated-document-storage.service.ts +1 -1
  109. package/src/system-agents/context-compaction.agent.ts +10 -9
  110. package/src/system-agents/delegated-agent-factory.ts +30 -6
  111. package/src/system-agents/memory-reranker.agent.ts +10 -9
  112. package/src/system-agents/memory.agent.ts +10 -9
  113. package/src/system-agents/recent-activity-title-refiner.agent.ts +13 -15
  114. package/src/system-agents/regular-chat-memory-digest.agent.ts +13 -12
  115. package/src/system-agents/skill-extractor.agent.ts +13 -12
  116. package/src/system-agents/skill-manager.agent.ts +13 -12
  117. package/src/system-agents/thread-router.agent.ts +11 -7
  118. package/src/system-agents/title-generator.agent.ts +13 -12
  119. package/src/tools/fetch-webpage.tool.ts +13 -13
  120. package/src/tools/memory-block.tool.ts +3 -1
  121. package/src/tools/plan-approval.tool.ts +4 -2
  122. package/src/tools/read-file-parts.tool.ts +10 -4
  123. package/src/tools/remember-memory.tool.ts +3 -1
  124. package/src/tools/research-topic.tool.ts +9 -5
  125. package/src/tools/search-web.tool.ts +16 -16
  126. package/src/tools/search.tool.ts +20 -5
  127. package/src/tools/team-think.tool.ts +61 -38
  128. package/src/utils/async.ts +5 -5
  129. package/src/utils/errors.ts +19 -18
  130. package/src/utils/sse-keepalive.ts +28 -25
  131. package/src/workers/bootstrap.ts +75 -11
  132. package/src/workers/memory-consolidation.worker.ts +82 -91
  133. package/src/workers/organization-learning.worker.ts +14 -4
  134. package/src/workers/regular-chat-memory-digest.runner.ts +105 -67
  135. package/src/workers/skill-extraction.runner.ts +97 -61
  136. package/src/workers/utils/repo-structure-extractor.ts +13 -8
  137. package/src/workers/utils/thread-message-query.ts +24 -24
  138. package/src/workers/worker-utils.ts +23 -4
  139. package/src/effect/helpers.ts +0 -123
@@ -6,7 +6,7 @@ import { Effect, Ref, Schema, Stream } from 'effect'
6
6
 
7
7
  import { aiLogger } from '../../config/logger'
8
8
  import type { RecordIdRef } from '../../db/record-id'
9
- import { effectTryMaybeAsync, makeEffectTryPromiseWithMessage } from '../../effect/helpers'
9
+ import { ERROR_TAGS } from '../../effect/errors'
10
10
  import { AgentConfigServiceTag, AgentFactoryServiceTag } from '../../effect/services'
11
11
  import {
12
12
  readRuntimeAgentIdentityOverrides,
@@ -40,28 +40,12 @@ interface ToolLoopGenerateResult {
40
40
  }
41
41
 
42
42
  export class ThreadTurnStreamingError extends Schema.TaggedErrorClass<ThreadTurnStreamingError>()(
43
- 'ThreadTurnStreamingError',
43
+ '@lota-sdk/core/ThreadTurnStreamingError',
44
44
  { message: Schema.String, cause: Schema.optional(Schema.Defect) },
45
45
  ) {}
46
46
 
47
- const effectTryPromise = makeEffectTryPromiseWithMessage(
48
- (message, cause) => new ThreadTurnStreamingError({ message, cause }),
49
- )
50
-
51
- function effectFromMaybeEffect<A>(
52
- evaluate: () => A | PromiseLike<A> | Effect.Effect<A, ThreadTurnStreamingError>,
53
- message: string,
54
- ): Effect.Effect<A, ThreadTurnStreamingError> {
55
- return Effect.try({ try: evaluate, catch: (error) => new ThreadTurnStreamingError({ message, cause: error }) }).pipe(
56
- Effect.flatMap((result) =>
57
- Effect.isEffect(result)
58
- ? result.pipe(Effect.mapError((error) => new ThreadTurnStreamingError({ message, cause: error })))
59
- : effectTryMaybeAsync(
60
- () => result,
61
- (error) => new ThreadTurnStreamingError({ message, cause: error }),
62
- ),
63
- ),
64
- )
47
+ function toThreadTurnStreamingError(message: string, cause: unknown): ThreadTurnStreamingError {
48
+ return new ThreadTurnStreamingError({ message, cause })
65
49
  }
66
50
 
67
51
  function hasUIMessageStream(value: unknown): value is UIMessageStreamResult {
@@ -90,7 +74,7 @@ function isTextTokenChunkType(chunkType: string | undefined): boolean {
90
74
  return chunkType === 'text-delta'
91
75
  }
92
76
 
93
- function buildFallbackResponseMessage(
77
+ export function buildFallbackResponseMessage(
94
78
  result: ToolLoopGenerateResult,
95
79
  ): Effect.Effect<ChatMessage, ThreadTurnStreamingError> {
96
80
  const parts: ChatMessage['parts'] = []
@@ -112,12 +96,6 @@ function buildFallbackResponseMessage(
112
96
  parts.push({ type: 'text', text })
113
97
  }
114
98
 
115
- if (parts.length === 0) {
116
- return Effect.fail(
117
- new ThreadTurnStreamingError({ message: 'Agent generate fallback did not produce any response parts.' }),
118
- )
119
- }
120
-
121
99
  return Effect.succeed({ id: Bun.randomUUIDv7(), role: 'assistant', parts })
122
100
  }
123
101
 
@@ -151,7 +129,7 @@ interface StreamAgentResponseParams {
151
129
  messages: ChatMessage[]
152
130
  tools: ToolSet
153
131
  observer: {
154
- run: <T>(fn: () => T | Promise<T>) => Promise<T>
132
+ run: <T>(fn: () => Promise<T>) => Promise<T>
155
133
  recordError: (error: unknown) => void
156
134
  recordAbort: (error: unknown) => void
157
135
  }
@@ -172,45 +150,54 @@ const streamAgentResponseEffect = Effect.fn('ThreadTurnStreaming.streamAgentResp
172
150
  const executionPlanInstructionSections =
173
151
  streamParams.includeExecutionPlanTools === false
174
152
  ? undefined
175
- : yield* effectFromMaybeEffect(
176
- () => ctx.getExecutionPlanInstructionSections(),
177
- 'Failed to load execution plan instructions.',
178
- ).pipe(Effect.withSpan('ThreadTurnStreaming.loadExecutionPlanInstructions'))
153
+ : yield* ctx.getExecutionPlanInstructionSections().pipe(
154
+ Effect.mapError((cause) => toThreadTurnStreamingError('Failed to load execution plan instructions.', cause)),
155
+ Effect.withSpan('ThreadTurnStreaming.loadExecutionPlanInstructions'),
156
+ )
179
157
 
158
+ const resolveAgent = ctx.turnHooks.resolveAgent
180
159
  const agentResolution = asRecord(
181
- yield* effectTryMaybeAsync(
182
- () =>
183
- ctx.turnHooks.resolveAgent?.({
184
- agentId: streamParams.agentId,
185
- mode: streamParams.mode,
186
- thread: ctx.thread,
187
- threadRef: ctx.threadRef,
188
- orgRef: ctx.orgRef,
189
- userRef: ctx.userRef,
190
- userName: ctx.userName,
191
- onboardingActive: ctx.onboardingActive,
192
- linearInstalled: ctx.linearInstalled,
193
- githubInstalled: ctx.githubInstalled,
194
- skills: streamParams.skills,
195
- additionalInstructionSections: streamParams.additionalInstructionSections,
196
- context: ctx.buildContextResult,
197
- }),
198
- (error) => new ThreadTurnStreamingError({ message: 'Failed to resolve the runtime agent.', cause: error }),
199
- ).pipe(Effect.withSpan('ThreadTurnStreaming.resolveAgent')),
160
+ resolveAgent
161
+ ? yield* Effect.tryPromise({
162
+ try: () =>
163
+ resolveAgent({
164
+ agentId: streamParams.agentId,
165
+ mode: streamParams.mode,
166
+ thread: ctx.thread,
167
+ threadRef: ctx.threadRef,
168
+ orgRef: ctx.orgRef,
169
+ userRef: ctx.userRef,
170
+ userName: ctx.userName,
171
+ onboardingActive: ctx.onboardingActive,
172
+ linearInstalled: ctx.linearInstalled,
173
+ githubInstalled: ctx.githubInstalled,
174
+ skills: streamParams.skills,
175
+ additionalInstructionSections: streamParams.additionalInstructionSections,
176
+ context: ctx.buildContextResult,
177
+ }),
178
+ catch: (cause) => toThreadTurnStreamingError('Failed to resolve the runtime agent.', cause),
179
+ }).pipe(Effect.withSpan('ThreadTurnStreaming.resolveAgent'))
180
+ : undefined,
200
181
  )
201
182
 
202
183
  const resolvedAgentId = readOptionalString(agentResolution?.agentId) ?? streamParams.agentId
203
184
  const latestUserMessage = [...streamParams.messages].reverse().find((message) => message.role === 'user')
204
185
  const latestUserMessageText = latestUserMessage ? extractMessageText(latestUserMessage).trim() : undefined
205
186
  const [preSeededMemoriesSection, learnedSkillsSection] = yield* Effect.all([
206
- effectFromMaybeEffect(
207
- () => ctx.getPreSeededMemoriesSection(resolvedAgentId),
208
- `Failed to load pre-seeded memories for ${resolvedAgentId}.`,
209
- ),
210
- effectFromMaybeEffect(
211
- () => ctx.getLearnedSkillsSection(resolvedAgentId, latestUserMessageText),
212
- `Failed to load learned skills for ${resolvedAgentId}.`,
213
- ),
187
+ ctx
188
+ .getPreSeededMemoriesSection(resolvedAgentId)
189
+ .pipe(
190
+ Effect.mapError((cause) =>
191
+ toThreadTurnStreamingError(`Failed to load pre-seeded memories for ${resolvedAgentId}.`, cause),
192
+ ),
193
+ ),
194
+ ctx
195
+ .getLearnedSkillsSection(resolvedAgentId, latestUserMessageText)
196
+ .pipe(
197
+ Effect.mapError((cause) =>
198
+ toThreadTurnStreamingError(`Failed to load learned skills for ${resolvedAgentId}.`, cause),
199
+ ),
200
+ ),
214
201
  ]).pipe(Effect.withSpan('ThreadTurnStreaming.loadMemoriesAndSkills'))
215
202
 
216
203
  const toolNames = new Set(Object.keys(streamParams.tools))
@@ -259,10 +246,10 @@ const streamAgentResponseEffect = Effect.fn('ThreadTurnStreaming.streamAgentResp
259
246
  hasRetrievalTools,
260
247
  })
261
248
 
262
- const modelMessages = yield* effectTryPromise(
263
- () => convertToModelMessages(streamParams.messages, { ignoreIncompleteToolCalls: true }),
264
- 'Failed to convert UI messages to model messages.',
265
- ).pipe(Effect.withSpan('ThreadTurnStreaming.convertModelMessages'))
249
+ const modelMessages = yield* Effect.tryPromise({
250
+ try: () => convertToModelMessages(streamParams.messages, { ignoreIncompleteToolCalls: true }),
251
+ catch: (cause) => toThreadTurnStreamingError('Failed to convert UI messages to model messages.', cause),
252
+ }).pipe(Effect.withSpan('ThreadTurnStreaming.convertModelMessages'))
266
253
 
267
254
  const agentFactory = agentFactoryConfig.createAgent[config.id]
268
255
  if (!agentFactory) {
@@ -281,10 +268,11 @@ const streamAgentResponseEffect = Effect.fn('ThreadTurnStreaming.streamAgentResp
281
268
  const resolvedAgentName = resolveRuntimeAgentDisplayName(agentConfig, agentIdentityOverrides, resolvedAgentId)
282
269
 
283
270
  const generateFallback = (cause: ThreadTurnStreamingError) =>
284
- effectTryPromise(
285
- () => streamParams.observer.run(() => agent.generate({ messages: modelMessages, abortSignal: agentAbortSignal })),
286
- `Agent generate fallback failed for ${resolvedAgentId}.`,
287
- ).pipe(
271
+ Effect.tryPromise({
272
+ try: () =>
273
+ streamParams.observer.run(() => agent.generate({ messages: modelMessages, abortSignal: agentAbortSignal })),
274
+ catch: (error) => toThreadTurnStreamingError(`Agent generate fallback failed for ${resolvedAgentId}.`, error),
275
+ }).pipe(
288
276
  Effect.tap(() =>
289
277
  Effect.sync(() => {
290
278
  aiLogger.warn`Agent stream failed for ${resolvedAgentId}; falling back to generate: ${cause.message}`
@@ -293,10 +281,11 @@ const streamAgentResponseEffect = Effect.fn('ThreadTurnStreaming.streamAgentResp
293
281
  Effect.flatMap((result) => buildFallbackResponseMessage(result as ToolLoopGenerateResult)),
294
282
  )
295
283
 
296
- const generateWithoutUiStream = effectTryPromise(
297
- () => streamParams.observer.run(() => agent.generate({ messages: modelMessages, abortSignal: agentAbortSignal })),
298
- `Agent generate failed for ${resolvedAgentId}.`,
299
- ).pipe(
284
+ const generateWithoutUiStream = Effect.tryPromise({
285
+ try: () =>
286
+ streamParams.observer.run(() => agent.generate({ messages: modelMessages, abortSignal: agentAbortSignal })),
287
+ catch: (cause) => toThreadTurnStreamingError(`Agent generate failed for ${resolvedAgentId}.`, cause),
288
+ }).pipe(
300
289
  Effect.tapError((error) =>
301
290
  Effect.sync(() => {
302
291
  if (agentAbortSignal.aborted) {
@@ -321,10 +310,12 @@ const streamAgentResponseEffect = Effect.fn('ThreadTurnStreaming.streamAgentResp
321
310
  return generatedResponse
322
311
  }
323
312
 
324
- const result = yield* effectTryPromise(
325
- () => streamParams.observer.run(() => agent.stream({ messages: modelMessages, abortSignal: agentAbortSignal })),
326
- `Agent stream failed for ${resolvedAgentId}.`,
327
- ).pipe(
313
+ const writer = streamParams.writer
314
+ const result = yield* Effect.tryPromise({
315
+ try: () =>
316
+ streamParams.observer.run(() => agent.stream({ messages: modelMessages, abortSignal: agentAbortSignal })),
317
+ catch: (cause) => toThreadTurnStreamingError(`Agent stream failed for ${resolvedAgentId}.`, cause),
318
+ }).pipe(
328
319
  Effect.tapError((error) =>
329
320
  Effect.sync(() => {
330
321
  if (agentAbortSignal.aborted) {
@@ -355,14 +346,12 @@ const streamAgentResponseEffect = Effect.fn('ThreadTurnStreaming.streamAgentResp
355
346
  resolveFinishedStream(withMessageCreatedAt(finishedResponseMessage, nowEpochMillis()))
356
347
  },
357
348
  }) as ReadableStream<ChatStreamChunk>
358
- const liveTurnTrace = streamParams.writer
359
- ? createLiveTurnTraceStreamObserver({
360
- traceId: `trace:${Bun.randomUUIDv7()}`,
361
- writer: streamParams.writer,
362
- agentId: resolvedAgentId,
363
- agentName: resolvedAgentName,
364
- })
365
- : null
349
+ const liveTurnTrace = createLiveTurnTraceStreamObserver({
350
+ traceId: `trace:${Bun.randomUUIDv7()}`,
351
+ writer,
352
+ agentId: resolvedAgentId,
353
+ agentName: resolvedAgentName,
354
+ })
366
355
  const streamStartedAt = performance.now()
367
356
  const firstVisibleOutputRecorded = yield* Ref.make(false)
368
357
  const firstTextTokenRecorded = yield* Ref.make(false)
@@ -393,21 +382,23 @@ const streamAgentResponseEffect = Effect.fn('ThreadTurnStreaming.streamAgentResp
393
382
  yield* Effect.annotateCurrentSpan({ ttftMs: elapsedMs, ttftChunkType: chunkType })
394
383
  }
395
384
 
396
- if (streamParams.writer) {
397
- yield* Effect.sync(() => {
398
- streamParams.writer?.write(value)
399
- liveTurnTrace?.observeChunk(value)
400
- })
401
- }
385
+ yield* Effect.sync(() => {
386
+ writer.write(value)
387
+ liveTurnTrace.observeChunk(value)
388
+ })
402
389
  }),
403
390
  ),
404
391
  Effect.withSpan('ThreadTurnStreaming.consumeUiStream'),
405
392
  Effect.andThen(
406
- effectTryPromise(() => finishedStream, `Agent run for ${resolvedAgentId} did not produce a response message.`),
393
+ Effect.tryPromise({
394
+ try: () => finishedStream,
395
+ catch: (cause) =>
396
+ toThreadTurnStreamingError(`Agent run for ${resolvedAgentId} did not produce a response message.`, cause),
397
+ }),
407
398
  ),
408
- Effect.catchTag('ThreadTurnStreamingError', generateFallback),
399
+ Effect.catchTag(ERROR_TAGS.ThreadTurnStreamingError, generateFallback),
409
400
  )
410
- liveTurnTrace?.finish()
401
+ liveTurnTrace.finish()
411
402
 
412
403
  for (const toolError of collectToolOutputErrors({ responseMessage: streamedResponse })) {
413
404
  aiLogger.error`Tool execution failed (agent=${resolvedAgentId}, tool=${toolError.toolName}, toolCallId=${toolError.toolCallId}): ${toolError.errorText}`
@@ -5,12 +5,12 @@ import { Context, Schema, Effect, Layer } from 'effect'
5
5
  import type { ResolvedAgentConfig } from '../../config/agent-defaults'
6
6
  import { ensureRecordId, recordIdToString } from '../../db/record-id'
7
7
  import { TABLES } from '../../db/tables'
8
- import { BadRequestError, ForbiddenError } from '../../effect/errors'
8
+ import { ERROR_TAGS, BadRequestError, ForbiddenError } from '../../effect/errors'
9
9
  import { AgentConfigServiceTag } from '../../effect/services'
10
10
  import { hasApprovalRespondedParts, isApprovalContinuationRequest } from '../../runtime/approval-continuation'
11
11
  import { shouldPlanNodeUseVisibleTurn } from '../../runtime/execution-plan-visibility'
12
12
  import { wrapResponseWithKeepalive } from '../../utils/sse-keepalive'
13
- import { BackgroundWorkService } from '../background-work.service'
13
+ import { BackgroundWorkServiceTag } from '../background-work.service'
14
14
  import type { makePlanExecutorService } from '../plan/plan-executor.service'
15
15
  import { PlanExecutorServiceTag } from '../plan/plan-executor.service'
16
16
  import type { makePlanRunService } from '../plan/plan-run.service'
@@ -67,14 +67,14 @@ export interface LaunchBackgroundThreadWorkResult {
67
67
  message: string
68
68
  }
69
69
 
70
- class ThreadTurnServiceError extends Schema.TaggedErrorClass<ThreadTurnServiceError>()('ThreadTurnServiceError', {
71
- message: Schema.String,
72
- cause: Schema.optional(Schema.Defect),
73
- }) {}
70
+ class ThreadTurnServiceError extends Schema.TaggedErrorClass<ThreadTurnServiceError>()(
71
+ ERROR_TAGS.ThreadTurnServiceError,
72
+ { message: Schema.String, cause: Schema.optional(Schema.Defect) },
73
+ ) {}
74
74
 
75
75
  interface ThreadTurnDeps {
76
76
  agentConfig: ResolvedAgentConfig
77
- background: Context.Service.Shape<typeof BackgroundWorkService>
77
+ background: Context.Service.Shape<typeof BackgroundWorkServiceTag>
78
78
  planExecutor: ReturnType<typeof makePlanExecutorService>
79
79
  planRun: ReturnType<typeof makePlanRunService>
80
80
  provideCurrentContext: <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, never>
@@ -428,14 +428,16 @@ function triggerPlanNodeTurnWith(
428
428
  deps: ThreadTurnDeps,
429
429
  params: { runId: string; nodeId: string; abortSignal?: AbortSignal; streamId?: string },
430
430
  ) {
431
- return triggerPlanNodeTurnEffect(deps, params).pipe(
432
- Effect.annotateSpans(
433
- compactSpanAttributes({
434
- turnKind: 'planTurn',
435
- streamId: params.streamId,
436
- planRunId: params.runId,
437
- planNodeId: params.nodeId,
438
- }),
431
+ return deps.provideCurrentContext(
432
+ triggerPlanNodeTurnEffect(deps, params).pipe(
433
+ Effect.annotateSpans(
434
+ compactSpanAttributes({
435
+ turnKind: 'planTurn',
436
+ streamId: params.streamId,
437
+ planRunId: params.runId,
438
+ planNodeId: params.nodeId,
439
+ }),
440
+ ),
439
441
  ),
440
442
  )
441
443
  }
@@ -475,7 +477,7 @@ export const ThreadTurnServiceLive = Layer.effect(
475
477
  const provideCurrentContext = <A, E, R>(effect: Effect.Effect<A, E, R>): Effect.Effect<A, E, never> =>
476
478
  effect.pipe(Effect.provide(currentContext)) as Effect.Effect<A, E, never>
477
479
  const agentConfig = yield* AgentConfigServiceTag
478
- const background = yield* BackgroundWorkService
480
+ const background = yield* BackgroundWorkServiceTag
479
481
  const planExecutor = yield* PlanExecutorServiceTag
480
482
  const planRun = yield* PlanRunServiceTag
481
483
  const thread = yield* ThreadServiceTag