@lota-sdk/core 0.4.8 → 0.4.10

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 (272) hide show
  1. package/package.json +11 -12
  2. package/src/ai/embedding-cache.ts +96 -22
  3. package/src/ai-gateway/ai-gateway.ts +766 -223
  4. package/src/config/agent-defaults.ts +189 -75
  5. package/src/config/agent-types.ts +54 -4
  6. package/src/config/background-processing.ts +1 -1
  7. package/src/config/constants.ts +8 -2
  8. package/src/config/index.ts +0 -1
  9. package/src/config/logger.ts +299 -19
  10. package/src/config/thread-defaults.ts +40 -20
  11. package/src/create-runtime.ts +200 -449
  12. package/src/db/base.service.ts +52 -28
  13. package/src/db/cursor-pagination.ts +71 -30
  14. package/src/db/memory-query-builder.ts +2 -1
  15. package/src/db/memory-store.helpers.ts +4 -7
  16. package/src/db/memory-store.ts +868 -601
  17. package/src/db/memory.ts +396 -280
  18. package/src/db/record-id.ts +32 -10
  19. package/src/db/schema-fingerprint.ts +30 -12
  20. package/src/db/service-normalization.ts +288 -0
  21. package/src/db/service.ts +912 -779
  22. package/src/db/startup.ts +153 -68
  23. package/src/db/transaction-conflict.ts +15 -0
  24. package/src/effect/awaitable-effect.ts +96 -0
  25. package/src/effect/errors.ts +121 -0
  26. package/src/effect/helpers.ts +123 -0
  27. package/src/effect/index.ts +24 -0
  28. package/src/effect/layers.ts +238 -0
  29. package/src/effect/runtime-ref.ts +25 -0
  30. package/src/effect/runtime.ts +46 -0
  31. package/src/effect/services.ts +61 -0
  32. package/src/effect/zod.ts +43 -0
  33. package/src/embeddings/provider.ts +128 -83
  34. package/src/index.ts +48 -1
  35. package/src/openrouter/direct-provider.ts +11 -35
  36. package/src/queues/autonomous-job.queue.ts +117 -73
  37. package/src/queues/context-compaction.queue.ts +50 -17
  38. package/src/queues/delayed-node-promotion.queue.ts +46 -17
  39. package/src/queues/document-processor.queue.ts +52 -77
  40. package/src/queues/memory-consolidation.queue.ts +47 -32
  41. package/src/queues/organization-learning.queue.ts +26 -4
  42. package/src/queues/plan-agent-heartbeat.queue.ts +71 -24
  43. package/src/queues/plan-scheduler.queue.ts +97 -33
  44. package/src/queues/post-chat-memory.queue.ts +56 -26
  45. package/src/queues/queue-factory.ts +227 -59
  46. package/src/queues/standalone-worker.ts +39 -0
  47. package/src/queues/title-generation.queue.ts +45 -11
  48. package/src/redis/connection.ts +182 -113
  49. package/src/redis/index.ts +6 -8
  50. package/src/redis/org-memory-lock.ts +60 -27
  51. package/src/redis/redis-lease-lock.ts +200 -121
  52. package/src/redis/runtime-connection.ts +20 -0
  53. package/src/redis/stream-context.ts +92 -46
  54. package/src/runtime/agent-identity-overrides.ts +2 -2
  55. package/src/runtime/agent-runtime-policy.ts +5 -2
  56. package/src/runtime/agent-stream-helpers.ts +24 -9
  57. package/src/runtime/chat-run-orchestration.ts +102 -19
  58. package/src/runtime/chat-run-registry.ts +36 -2
  59. package/src/runtime/context-compaction/context-compaction-runtime.ts +107 -0
  60. package/src/runtime/{context-compaction.ts → context-compaction/context-compaction.ts} +161 -94
  61. package/src/runtime/domain-layer.ts +192 -0
  62. package/src/runtime/execution-plan-visibility.ts +2 -2
  63. package/src/runtime/execution-plan.ts +42 -15
  64. package/src/runtime/graph-designer.ts +16 -4
  65. package/src/runtime/helper-model.ts +139 -48
  66. package/src/runtime/index.ts +7 -8
  67. package/src/runtime/indexed-repositories-policy.ts +3 -3
  68. package/src/runtime/{memory-block.ts → memory/memory-block.ts} +50 -36
  69. package/src/runtime/{memory-digest-policy.ts → memory/memory-digest-policy.ts} +1 -1
  70. package/src/runtime/{memory-pipeline.ts → memory/memory-pipeline.ts} +54 -67
  71. package/src/runtime/{memory-prompts-fact.ts → memory/memory-prompts-fact.ts} +2 -2
  72. package/src/runtime/memory/memory-scope.ts +53 -0
  73. package/src/runtime/plugin-resolution.ts +124 -25
  74. package/src/runtime/plugin-types.ts +9 -1
  75. package/src/runtime/post-turn-side-effects.ts +177 -130
  76. package/src/runtime/retrieval-adapters.ts +40 -6
  77. package/src/runtime/runtime-accessors.ts +92 -0
  78. package/src/runtime/runtime-config.ts +150 -61
  79. package/src/runtime/runtime-extensions.ts +23 -25
  80. package/src/runtime/runtime-lifecycle.ts +124 -0
  81. package/src/runtime/runtime-services.ts +386 -0
  82. package/src/runtime/runtime-token.ts +47 -0
  83. package/src/runtime/social-chat/social-chat-agent-runner.ts +159 -0
  84. package/src/runtime/{social-chat-history.ts → social-chat/social-chat-history.ts} +51 -20
  85. package/src/runtime/social-chat/social-chat.ts +630 -0
  86. package/src/runtime/specialist-runner.ts +36 -10
  87. package/src/runtime/team-consultation/team-consultation-orchestrator.ts +433 -0
  88. package/src/runtime/{team-consultation-prompts.ts → team-consultation/team-consultation-prompts.ts} +6 -2
  89. package/src/runtime/thread-chat-helpers.ts +2 -2
  90. package/src/runtime/thread-plan-turn.ts +2 -1
  91. package/src/runtime/thread-turn-context.ts +183 -111
  92. package/src/runtime/turn-lifecycle.ts +93 -27
  93. package/src/services/agent-activity.service.ts +287 -203
  94. package/src/services/agent-executor.service.ts +253 -149
  95. package/src/services/artifact.service.ts +231 -149
  96. package/src/services/attachment.service.ts +171 -115
  97. package/src/services/autonomous-job.service.ts +890 -491
  98. package/src/services/background-work.service.ts +54 -0
  99. package/src/services/chat-run-registry.service.ts +13 -1
  100. package/src/services/context-compaction.service.ts +136 -86
  101. package/src/services/document-chunk.service.ts +151 -88
  102. package/src/services/execution-plan/execution-plan-approval.ts +26 -0
  103. package/src/services/execution-plan/execution-plan-context.ts +29 -0
  104. package/src/services/execution-plan/execution-plan-graph.ts +278 -0
  105. package/src/services/execution-plan/execution-plan-schedule.ts +84 -0
  106. package/src/services/execution-plan/execution-plan-spec.ts +75 -0
  107. package/src/services/execution-plan/execution-plan.service.ts +1041 -0
  108. package/src/services/feedback-loop.service.ts +132 -76
  109. package/src/services/global-orchestrator.service.ts +101 -168
  110. package/src/services/graph-full-routing.ts +193 -0
  111. package/src/services/index.ts +19 -21
  112. package/src/services/institutional-memory.service.ts +213 -125
  113. package/src/services/learned-skill.service.ts +368 -260
  114. package/src/services/memory/memory-conversation.ts +95 -0
  115. package/src/services/memory/memory-errors.ts +27 -0
  116. package/src/services/memory/memory-org-memory.ts +50 -0
  117. package/src/services/memory/memory-preseeded.ts +86 -0
  118. package/src/services/memory/memory-rerank.ts +297 -0
  119. package/src/services/{memory-utils.ts → memory/memory-utils.ts} +6 -5
  120. package/src/services/memory/memory.service.ts +674 -0
  121. package/src/services/memory/rerank.service.ts +201 -0
  122. package/src/services/monitoring-window.service.ts +92 -70
  123. package/src/services/mutating-approval.service.ts +62 -53
  124. package/src/services/node-workspace.service.ts +141 -98
  125. package/src/services/notification.service.ts +29 -16
  126. package/src/services/organization-member.service.ts +120 -66
  127. package/src/services/organization.service.ts +153 -77
  128. package/src/services/ownership-dispatcher.service.ts +456 -263
  129. package/src/services/plan/plan-agent-heartbeat.service.ts +234 -0
  130. package/src/services/plan/plan-agent-query.service.ts +322 -0
  131. package/src/services/{plan-approval.service.ts → plan/plan-approval.service.ts} +45 -22
  132. package/src/services/plan/plan-artifact.service.ts +60 -0
  133. package/src/services/plan/plan-builder.service.ts +76 -0
  134. package/src/services/plan/plan-checkpoint.service.ts +103 -0
  135. package/src/services/{plan-compiler.service.ts → plan/plan-compiler.service.ts} +26 -9
  136. package/src/services/plan/plan-completion-side-effects.ts +169 -0
  137. package/src/services/plan/plan-coordination.service.ts +181 -0
  138. package/src/services/plan/plan-cycle.service.ts +405 -0
  139. package/src/services/plan/plan-deadline.service.ts +533 -0
  140. package/src/services/plan/plan-event-delivery.service.ts +266 -0
  141. package/src/services/plan/plan-executor-context.ts +35 -0
  142. package/src/services/plan/plan-executor-graph.ts +522 -0
  143. package/src/services/plan/plan-executor-helpers.ts +307 -0
  144. package/src/services/plan/plan-executor-persistence.ts +209 -0
  145. package/src/services/plan/plan-executor.service.ts +1737 -0
  146. package/src/services/{plan-helpers.ts → plan/plan-helpers.ts} +1 -1
  147. package/src/services/{plan-run-data.ts → plan/plan-run-data.ts} +4 -4
  148. package/src/services/plan/plan-run-serialization.ts +15 -0
  149. package/src/services/plan/plan-run.service.ts +637 -0
  150. package/src/services/plan/plan-scheduler.service.ts +379 -0
  151. package/src/services/plan/plan-template.service.ts +224 -0
  152. package/src/services/plan/plan-transaction-events.ts +36 -0
  153. package/src/services/plan/plan-validator.service.ts +907 -0
  154. package/src/services/plan/plan-workspace.service.ts +131 -0
  155. package/src/services/plugin-executor.service.ts +102 -68
  156. package/src/services/quality-metrics.service.ts +112 -94
  157. package/src/services/queue-job.service.ts +288 -231
  158. package/src/services/recent-activity-title.service.ts +73 -36
  159. package/src/services/recent-activity.service.ts +274 -259
  160. package/src/services/skill-resolver.service.ts +38 -12
  161. package/src/services/social-chat-history.service.ts +190 -122
  162. package/src/services/system-executor.service.ts +96 -61
  163. package/src/services/thread/thread-active-run.ts +203 -0
  164. package/src/services/thread/thread-bootstrap.ts +385 -0
  165. package/src/services/thread/thread-listing.ts +199 -0
  166. package/src/services/thread/thread-memory-block.ts +130 -0
  167. package/src/services/thread/thread-message.service.ts +379 -0
  168. package/src/services/thread/thread-record-store.ts +155 -0
  169. package/src/services/thread/thread-title.service.ts +74 -0
  170. package/src/services/thread/thread-turn-execution.ts +280 -0
  171. package/src/services/thread/thread-turn-message-context.ts +73 -0
  172. package/src/services/thread/thread-turn-preparation.service.ts +1148 -0
  173. package/src/services/thread/thread-turn-streaming.ts +403 -0
  174. package/src/services/thread/thread-turn-tracing.ts +35 -0
  175. package/src/services/thread/thread-turn.ts +376 -0
  176. package/src/services/thread/thread.service.ts +344 -0
  177. package/src/services/user.service.ts +82 -32
  178. package/src/services/write-intent-validator.service.ts +63 -51
  179. package/src/storage/attachment-parser.ts +69 -27
  180. package/src/storage/attachment-storage.service.ts +334 -275
  181. package/src/storage/generated-document-storage.service.ts +66 -34
  182. package/src/system-agents/agent-result.ts +3 -1
  183. package/src/system-agents/context-compaction.agent.ts +3 -3
  184. package/src/system-agents/delegated-agent-factory.ts +159 -90
  185. package/src/system-agents/helper-agent-options.ts +1 -1
  186. package/src/system-agents/memory-reranker.agent.ts +3 -3
  187. package/src/system-agents/memory.agent.ts +3 -3
  188. package/src/system-agents/recent-activity-title-refiner.agent.ts +3 -3
  189. package/src/system-agents/regular-chat-memory-digest.agent.ts +3 -3
  190. package/src/system-agents/skill-extractor.agent.ts +3 -3
  191. package/src/system-agents/skill-manager.agent.ts +3 -3
  192. package/src/system-agents/thread-router.agent.ts +157 -113
  193. package/src/system-agents/title-generator.agent.ts +3 -3
  194. package/src/tools/execution-plan.tool.ts +241 -171
  195. package/src/tools/fetch-webpage.tool.ts +29 -18
  196. package/src/tools/firecrawl-client.ts +26 -6
  197. package/src/tools/index.ts +1 -0
  198. package/src/tools/memory-block.tool.ts +14 -6
  199. package/src/tools/plan-approval.tool.ts +57 -47
  200. package/src/tools/read-file-parts.tool.ts +44 -33
  201. package/src/tools/remember-memory.tool.ts +65 -45
  202. package/src/tools/search-web.tool.ts +33 -22
  203. package/src/tools/search.tool.ts +41 -29
  204. package/src/tools/team-think.tool.ts +125 -84
  205. package/src/tools/user-questions.tool.ts +4 -3
  206. package/src/tools/web-tool-shared.ts +6 -0
  207. package/src/utils/async.ts +25 -22
  208. package/src/utils/crypto.ts +21 -0
  209. package/src/utils/date-time.ts +40 -1
  210. package/src/utils/errors.ts +111 -20
  211. package/src/utils/hono-error-handler.ts +24 -39
  212. package/src/utils/index.ts +2 -1
  213. package/src/utils/null-proto-record.ts +41 -0
  214. package/src/utils/sse-keepalive.ts +124 -21
  215. package/src/workers/bootstrap.ts +164 -52
  216. package/src/workers/memory-consolidation.worker.ts +325 -237
  217. package/src/workers/organization-learning.worker.ts +50 -16
  218. package/src/workers/regular-chat-memory-digest.helpers.ts +28 -27
  219. package/src/workers/regular-chat-memory-digest.runner.ts +185 -114
  220. package/src/workers/skill-extraction.runner.ts +176 -93
  221. package/src/workers/utils/file-section-chunker.ts +8 -10
  222. package/src/workers/utils/repo-structure-extractor.ts +349 -260
  223. package/src/workers/utils/repomix-file-sections.ts +2 -2
  224. package/src/workers/utils/thread-message-query.ts +97 -38
  225. package/src/workers/worker-utils.ts +74 -31
  226. package/src/config/debug-logger.ts +0 -47
  227. package/src/config/search.ts +0 -3
  228. package/src/redis/connection-accessor.ts +0 -26
  229. package/src/runtime/agent-types.ts +0 -1
  230. package/src/runtime/context-compaction-runtime.ts +0 -87
  231. package/src/runtime/memory-scope.ts +0 -43
  232. package/src/runtime/social-chat-agent-runner.ts +0 -118
  233. package/src/runtime/social-chat.ts +0 -516
  234. package/src/runtime/team-consultation-orchestrator.ts +0 -272
  235. package/src/services/adaptive-playbook.service.ts +0 -152
  236. package/src/services/artifact-provenance.service.ts +0 -172
  237. package/src/services/chat-attachments.service.ts +0 -17
  238. package/src/services/context-compaction-runtime.singleton.ts +0 -13
  239. package/src/services/execution-plan.service.ts +0 -1118
  240. package/src/services/memory.service.ts +0 -914
  241. package/src/services/plan-agent-heartbeat.service.ts +0 -136
  242. package/src/services/plan-agent-query.service.ts +0 -267
  243. package/src/services/plan-artifact.service.ts +0 -50
  244. package/src/services/plan-builder.service.ts +0 -67
  245. package/src/services/plan-checkpoint.service.ts +0 -81
  246. package/src/services/plan-completion-side-effects.ts +0 -80
  247. package/src/services/plan-coordination.service.ts +0 -157
  248. package/src/services/plan-cycle.service.ts +0 -284
  249. package/src/services/plan-deadline.service.ts +0 -430
  250. package/src/services/plan-event-delivery.service.ts +0 -166
  251. package/src/services/plan-executor.service.ts +0 -1950
  252. package/src/services/plan-run.service.ts +0 -515
  253. package/src/services/plan-scheduler.service.ts +0 -240
  254. package/src/services/plan-template.service.ts +0 -177
  255. package/src/services/plan-validator.service.ts +0 -818
  256. package/src/services/plan-workspace.service.ts +0 -83
  257. package/src/services/rerank.service.ts +0 -156
  258. package/src/services/thread-message.service.ts +0 -275
  259. package/src/services/thread-plan-registry.service.ts +0 -22
  260. package/src/services/thread-title.service.ts +0 -39
  261. package/src/services/thread-turn-preparation.service.ts +0 -1147
  262. package/src/services/thread-turn.ts +0 -172
  263. package/src/services/thread.service.ts +0 -869
  264. package/src/utils/env.ts +0 -8
  265. /package/src/runtime/{context-compaction-constants.ts → context-compaction/context-compaction-constants.ts} +0 -0
  266. /package/src/runtime/{memory-format.ts → memory/memory-format.ts} +0 -0
  267. /package/src/runtime/{memory-prompts-parse.ts → memory/memory-prompts-parse.ts} +0 -0
  268. /package/src/runtime/{memory-prompts-update.ts → memory/memory-prompts-update.ts} +0 -0
  269. /package/src/runtime/{social-chat-prompts.ts → social-chat/social-chat-prompts.ts} +0 -0
  270. /package/src/services/{plan-node-spec.ts → plan/plan-node-spec.ts} +0 -0
  271. /package/src/services/{thread-constants.ts → thread/thread-constants.ts} +0 -0
  272. /package/src/services/{thread.types.ts → thread/thread.types.ts} +0 -0
@@ -0,0 +1,376 @@
1
+ import type { ChatMessage } from '@lota-sdk/shared'
2
+ import { createUIMessageStream } from 'ai'
3
+ import { Context, Schema, Effect, Layer } from 'effect'
4
+
5
+ import { ensureRecordId, recordIdToString } from '../../db/record-id'
6
+ import { TABLES } from '../../db/tables'
7
+ import { BadRequestError } from '../../effect/errors'
8
+ import { runPromise } from '../../effect/runtime'
9
+ import { hasApprovalRespondedParts, isApprovalContinuationRequest } from '../../runtime/approval-continuation'
10
+ import { shouldPlanNodeUseVisibleTurn } from '../../runtime/execution-plan-visibility'
11
+ import { wrapResponseWithKeepalive } from '../../utils/sse-keepalive'
12
+ import type { makePlanExecutorService } from '../plan/plan-executor.service'
13
+ import { PlanExecutorServiceTag } from '../plan/plan-executor.service'
14
+ import type { makePlanRunService } from '../plan/plan-run.service'
15
+ import { PlanRunServiceTag } from '../plan/plan-run.service'
16
+ import type { makeUserService } from '../user.service'
17
+ import { UserServiceTag } from '../user.service'
18
+ import type {
19
+ PreparedThreadTurnResult,
20
+ ThreadApprovalContinuationParams,
21
+ ThreadPlanTurnParams,
22
+ ThreadTurnParams,
23
+ makeThreadTurnPreparationService,
24
+ } from './thread-turn-preparation.service'
25
+ import { ThreadTurnPreparationServiceTag } from './thread-turn-preparation.service'
26
+ import { buildThreadTurnSpanAttributes, compactSpanAttributes } from './thread-turn-tracing'
27
+ import type { makeThreadService } from './thread.service'
28
+ import { ThreadServiceTag } from './thread.service'
29
+
30
+ export { hasApprovalRespondedParts, isApprovalContinuationRequest }
31
+ export { wrapResponseWithKeepalive }
32
+ export type { PreparedThreadTurnResult }
33
+ export type { ThreadPlanTurnParams }
34
+
35
+ class ThreadTurnServiceError extends Schema.TaggedErrorClass<ThreadTurnServiceError>()('ThreadTurnServiceError', {
36
+ message: Schema.String,
37
+ cause: Schema.optional(Schema.Defect),
38
+ }) {}
39
+
40
+ interface ThreadTurnDeps {
41
+ planExecutor: ReturnType<typeof makePlanExecutorService>
42
+ planRun: ReturnType<typeof makePlanRunService>
43
+ thread: ReturnType<typeof makeThreadService>
44
+ threadTurnPreparation: ReturnType<typeof makeThreadTurnPreparationService>
45
+ user: ReturnType<typeof makeUserService>
46
+ }
47
+
48
+ const createThreadApprovalContinuationStreamEffect = Effect.fn('ThreadTurn.createApprovalContinuationStream')(
49
+ function* (deps: ThreadTurnDeps, params: ThreadApprovalContinuationParams) {
50
+ const currentContext = yield* Effect.context()
51
+ const runPromiseWithCurrentContext = Effect.runPromiseWith(currentContext)
52
+ const prepared = yield* deps.threadTurnPreparation.prepareThreadRunCoreEffect({
53
+ ...params,
54
+ kind: 'approvalContinuation',
55
+ })
56
+ return createUIMessageStream<ChatMessage>({
57
+ originalMessages: prepared.originalMessages,
58
+ onError: (error) => (error instanceof Error ? error.message : 'Approval continuation stream failed.'),
59
+ execute: ({ writer }) =>
60
+ runPromiseWithCurrentContext(
61
+ prepared.run(writer).pipe(Effect.withSpan('ThreadTurn.executeApprovalContinuationStream'), Effect.asVoid),
62
+ ),
63
+ })
64
+ },
65
+ )
66
+
67
+ function createThreadApprovalContinuationStreamWith(deps: ThreadTurnDeps, params: ThreadApprovalContinuationParams) {
68
+ return createThreadApprovalContinuationStreamEffect(deps, params).pipe(
69
+ Effect.annotateSpans(
70
+ buildThreadTurnSpanAttributes({
71
+ threadRef: params.threadRef,
72
+ orgRef: params.orgRef,
73
+ userRef: params.userRef,
74
+ kind: 'approvalContinuation',
75
+ streamId: params.streamId,
76
+ threadType: params.thread.type,
77
+ }),
78
+ ),
79
+ )
80
+ }
81
+
82
+ const createThreadNativeToolApprovalStreamEffect = Effect.fn('ThreadTurn.createNativeToolApprovalStream')(function* (
83
+ deps: ThreadTurnDeps,
84
+ params: ThreadApprovalContinuationParams,
85
+ ) {
86
+ const currentContext = yield* Effect.context()
87
+ const runPromiseWithCurrentContext = Effect.runPromiseWith(currentContext)
88
+ const prepared = yield* deps.threadTurnPreparation.prepareThreadRunCoreEffect({
89
+ ...params,
90
+ kind: 'nativeToolApprovalTurn',
91
+ })
92
+ return createUIMessageStream<ChatMessage>({
93
+ originalMessages: prepared.originalMessages,
94
+ onError: (error) => (error instanceof Error ? error.message : 'Native tool approval stream failed.'),
95
+ execute: ({ writer }) =>
96
+ runPromiseWithCurrentContext(
97
+ prepared.run(writer).pipe(Effect.withSpan('ThreadTurn.executeNativeToolApprovalStream'), Effect.asVoid),
98
+ ),
99
+ })
100
+ })
101
+
102
+ function createThreadNativeToolApprovalStreamWith(deps: ThreadTurnDeps, params: ThreadApprovalContinuationParams) {
103
+ return createThreadNativeToolApprovalStreamEffect(deps, params).pipe(
104
+ Effect.annotateSpans(
105
+ buildThreadTurnSpanAttributes({
106
+ threadRef: params.threadRef,
107
+ orgRef: params.orgRef,
108
+ userRef: params.userRef,
109
+ kind: 'nativeToolApprovalTurn',
110
+ streamId: params.streamId,
111
+ threadType: params.thread.type,
112
+ }),
113
+ ),
114
+ )
115
+ }
116
+
117
+ const createThreadTurnStreamEffect = Effect.fn('ThreadTurn.createThreadTurnStream')(function* (
118
+ deps: ThreadTurnDeps,
119
+ params: ThreadTurnParams,
120
+ ) {
121
+ const currentContext = yield* Effect.context()
122
+ const runPromiseWithCurrentContext = Effect.runPromiseWith(currentContext)
123
+ const prepared = yield* deps.threadTurnPreparation.prepareThreadRunCoreEffect({ ...params, kind: 'userTurn' })
124
+ return createUIMessageStream<ChatMessage>({
125
+ originalMessages: prepared.originalMessages,
126
+ onError: (error) => (error instanceof Error ? error.message : 'Chat stream failed.'),
127
+ execute: ({ writer }) =>
128
+ runPromiseWithCurrentContext(
129
+ prepared.run(writer).pipe(Effect.withSpan('ThreadTurn.executeThreadTurnStream'), Effect.asVoid),
130
+ ),
131
+ })
132
+ })
133
+
134
+ function createThreadTurnStreamWith(deps: ThreadTurnDeps, params: ThreadTurnParams) {
135
+ return createThreadTurnStreamEffect(deps, params).pipe(
136
+ Effect.annotateSpans(
137
+ buildThreadTurnSpanAttributes({
138
+ threadRef: params.threadRef,
139
+ orgRef: params.orgRef,
140
+ userRef: params.userRef,
141
+ kind: 'userTurn',
142
+ streamId: params.streamId,
143
+ threadType: params.thread.type,
144
+ }),
145
+ ),
146
+ )
147
+ }
148
+
149
+ const runThreadTurnInBackgroundEffect = Effect.fn('ThreadTurn.runThreadTurnInBackground')(function* (
150
+ deps: ThreadTurnDeps,
151
+ params: ThreadTurnParams,
152
+ ) {
153
+ const prepared = yield* deps.threadTurnPreparation.prepareThreadRunCoreEffect({ ...params, kind: 'userTurn' })
154
+ return yield* prepared.run().pipe(Effect.withSpan('ThreadTurn.executeBackgroundTurn'))
155
+ })
156
+
157
+ function runThreadTurnInBackgroundWith(deps: ThreadTurnDeps, params: ThreadTurnParams) {
158
+ return runThreadTurnInBackgroundEffect(deps, params).pipe(
159
+ Effect.annotateSpans(
160
+ buildThreadTurnSpanAttributes({
161
+ threadRef: params.threadRef,
162
+ orgRef: params.orgRef,
163
+ userRef: params.userRef,
164
+ kind: 'background',
165
+ streamId: params.streamId,
166
+ threadType: params.thread.type,
167
+ agentId: params.agentIdOverride,
168
+ }),
169
+ ),
170
+ )
171
+ }
172
+
173
+ const triggerPlanNodeTurnEffect = Effect.fn('ThreadTurn.triggerPlanNodeTurn')(function* (
174
+ deps: ThreadTurnDeps,
175
+ params: { runId: string; nodeId: string; abortSignal?: AbortSignal; streamId?: string },
176
+ ) {
177
+ const run = yield* deps.planRun.getRunById(params.runId)
178
+ const spec = yield* deps.planRun.getPlanSpecById(run.planSpecId)
179
+ const nodeSpec = yield* deps.planRun.getNodeSpecByNodeId(spec.id, params.nodeId)
180
+
181
+ if (!shouldPlanNodeUseVisibleTurn(spec, nodeSpec) || nodeSpec.owner.executorType !== 'agent') {
182
+ return yield* new BadRequestError({
183
+ message: `Plan node "${params.nodeId}" is not eligible for a visible plan turn.`,
184
+ })
185
+ }
186
+
187
+ let activeRun = run
188
+ let nodeRun = yield* deps.planRun.getNodeRunByNodeId(run.id, params.nodeId)
189
+ if (nodeRun.status === 'ready') {
190
+ yield* Effect.tryPromise({
191
+ try: () => deps.planExecutor.transitionNodeToRunning({ runId: params.runId, nodeId: params.nodeId }),
192
+ catch: (cause) => new ThreadTurnServiceError({ message: 'Failed to transition plan node to running.', cause }),
193
+ })
194
+ activeRun = yield* deps.planRun.getRunById(params.runId)
195
+ nodeRun = yield* deps.planRun.getNodeRunByNodeId(run.id, params.nodeId)
196
+ }
197
+
198
+ if (nodeRun.status !== 'running') {
199
+ return { assistantMessages: [], inputMessageId: undefined }
200
+ }
201
+
202
+ const thread = yield* deps.thread.getThread(activeRun.threadId)
203
+ const userRef = ensureRecordId(thread.userId, TABLES.USER)
204
+ const [artifacts, nodeRuns, nodeSpecs, userName] = yield* Effect.all([
205
+ deps.planRun.listArtifacts(activeRun.id),
206
+ deps.planRun.listNodeRuns(activeRun.id),
207
+ deps.planRun.listNodeSpecs(spec.id),
208
+ deps.user.getUser(recordIdToString(userRef, TABLES.USER)).pipe(
209
+ Effect.map((user) => user.name),
210
+ Effect.catch(() => Effect.succeed(undefined as string | undefined)),
211
+ ),
212
+ ]).pipe(Effect.withSpan('ThreadTurn.loadPlanTurnContext'))
213
+
214
+ const inputArtifacts = artifacts
215
+ .filter((artifact) => nodeSpec.upstreamNodeIds.includes(artifact.nodeId))
216
+ .map((artifact) => ({
217
+ name: artifact.name,
218
+ kind: artifact.kind,
219
+ ...(artifact.description ? { description: artifact.description } : {}),
220
+ ...(artifact.content !== undefined ? { content: artifact.content } : {}),
221
+ ...(artifact.payload !== undefined ? { payload: artifact.payload } : {}),
222
+ ...(artifact.publishedArtifactId
223
+ ? { publishedArtifactId: recordIdToString(artifact.publishedArtifactId, TABLES.ARTIFACT) }
224
+ : {}),
225
+ }))
226
+ const upstreamNodeSpecs = new Map(nodeSpecs.map((upstreamNodeSpec) => [upstreamNodeSpec.nodeId, upstreamNodeSpec]))
227
+ const upstreamHandoffs = nodeRuns
228
+ .filter((candidate) => nodeSpec.upstreamNodeIds.includes(candidate.nodeId) && candidate.latestNotes)
229
+ .map((candidate) => ({
230
+ nodeId: candidate.nodeId,
231
+ label: upstreamNodeSpecs.get(candidate.nodeId)?.label ?? candidate.nodeId,
232
+ ownerRef: upstreamNodeSpecs.get(candidate.nodeId)?.owner.ref ?? 'system',
233
+ ownerType: upstreamNodeSpecs.get(candidate.nodeId)?.owner.executorType ?? 'system',
234
+ summary: candidate.latestNotes ?? undefined,
235
+ }))
236
+
237
+ const threadRef = ensureRecordId(activeRun.threadId, TABLES.THREAD)
238
+ const orgRef = ensureRecordId(activeRun.organizationId, TABLES.ORGANIZATION)
239
+ const prepared = yield* deps.threadTurnPreparation.prepareThreadRunCoreEffect({
240
+ kind: 'planTurn',
241
+ thread,
242
+ threadRef,
243
+ orgRef,
244
+ userRef,
245
+ userName,
246
+ abortSignal: params.abortSignal,
247
+ streamId: params.streamId,
248
+ planTurn: {
249
+ runId: params.runId,
250
+ nodeId: params.nodeId,
251
+ planTitle: spec.title,
252
+ nodeSpec,
253
+ nodeRun,
254
+ resolvedInput: nodeRun.resolvedInput ?? {},
255
+ inputArtifacts,
256
+ upstreamHandoffs,
257
+ },
258
+ })
259
+ return yield* prepared.run().pipe(Effect.withSpan('ThreadTurn.executePlanTurn'))
260
+ })
261
+
262
+ function triggerPlanNodeTurnWith(
263
+ deps: ThreadTurnDeps,
264
+ params: { runId: string; nodeId: string; abortSignal?: AbortSignal; streamId?: string },
265
+ ) {
266
+ return triggerPlanNodeTurnEffect(deps, params).pipe(
267
+ Effect.annotateSpans(
268
+ compactSpanAttributes({
269
+ turnKind: 'planTurn',
270
+ streamId: params.streamId,
271
+ planRunId: params.runId,
272
+ planNodeId: params.nodeId,
273
+ }),
274
+ ),
275
+ )
276
+ }
277
+
278
+ export function makeThreadTurnService(deps: ThreadTurnDeps) {
279
+ return {
280
+ createThreadApprovalContinuationStream(params: ThreadApprovalContinuationParams) {
281
+ return createThreadApprovalContinuationStreamWith(deps, params)
282
+ },
283
+ createThreadNativeToolApprovalStream(params: ThreadApprovalContinuationParams) {
284
+ return createThreadNativeToolApprovalStreamWith(deps, params)
285
+ },
286
+ createThreadTurnStream(params: ThreadTurnParams) {
287
+ return createThreadTurnStreamWith(deps, params)
288
+ },
289
+ runThreadTurnInBackground(params: ThreadTurnParams) {
290
+ return runThreadTurnInBackgroundWith(deps, params)
291
+ },
292
+ triggerPlanNodeTurn(params: { runId: string; nodeId: string; abortSignal?: AbortSignal; streamId?: string }) {
293
+ return triggerPlanNodeTurnWith(deps, params)
294
+ },
295
+ } as const
296
+ }
297
+
298
+ export class ThreadTurnServiceTag extends Context.Service<
299
+ ThreadTurnServiceTag,
300
+ ReturnType<typeof makeThreadTurnService>
301
+ >()('@lota-sdk/core/ThreadTurnService') {}
302
+
303
+ export const ThreadTurnServiceLive = Layer.effect(
304
+ ThreadTurnServiceTag,
305
+ Effect.gen(function* () {
306
+ const planExecutor = yield* PlanExecutorServiceTag
307
+ const planRun = yield* PlanRunServiceTag
308
+ const thread = yield* ThreadServiceTag
309
+ const threadTurnPreparation = yield* ThreadTurnPreparationServiceTag
310
+ const user = yield* UserServiceTag
311
+ return makeThreadTurnService({ planExecutor, planRun, thread, threadTurnPreparation, user })
312
+ }),
313
+ )
314
+
315
+ const createThreadApprovalContinuationStreamWithRuntime = Effect.fn(
316
+ 'ThreadTurn.createApprovalContinuationStreamWithRuntime',
317
+ )(function* (params: ThreadApprovalContinuationParams) {
318
+ const threadTurnService = yield* ThreadTurnServiceTag
319
+ return yield* threadTurnService.createThreadApprovalContinuationStream(params)
320
+ })
321
+
322
+ const createThreadNativeToolApprovalStreamWithRuntime = Effect.fn(
323
+ 'ThreadTurn.createNativeToolApprovalStreamWithRuntime',
324
+ )(function* (params: ThreadApprovalContinuationParams) {
325
+ const threadTurnService = yield* ThreadTurnServiceTag
326
+ return yield* threadTurnService.createThreadNativeToolApprovalStream(params)
327
+ })
328
+
329
+ const createThreadTurnStreamWithRuntime = Effect.fn('ThreadTurn.createThreadTurnStreamWithRuntime')(function* (
330
+ params: ThreadTurnParams,
331
+ ) {
332
+ const threadTurnService = yield* ThreadTurnServiceTag
333
+ return yield* threadTurnService.createThreadTurnStream(params)
334
+ })
335
+
336
+ const runThreadTurnInBackgroundWithRuntime = Effect.fn('ThreadTurn.runThreadTurnInBackgroundWithRuntime')(function* (
337
+ params: ThreadTurnParams,
338
+ ) {
339
+ const threadTurnService = yield* ThreadTurnServiceTag
340
+ return yield* threadTurnService.runThreadTurnInBackground(params)
341
+ })
342
+
343
+ const triggerPlanNodeTurnWithRuntime = Effect.fn('ThreadTurn.triggerPlanNodeTurnWithRuntime')(function* (params: {
344
+ runId: string
345
+ nodeId: string
346
+ abortSignal?: AbortSignal
347
+ streamId?: string
348
+ }) {
349
+ const threadTurnService = yield* ThreadTurnServiceTag
350
+ return yield* threadTurnService.triggerPlanNodeTurn(params)
351
+ })
352
+
353
+ export function createThreadApprovalContinuationStream(params: ThreadApprovalContinuationParams) {
354
+ return runPromise(createThreadApprovalContinuationStreamWithRuntime(params))
355
+ }
356
+
357
+ export function createThreadNativeToolApprovalStream(params: ThreadApprovalContinuationParams) {
358
+ return runPromise(createThreadNativeToolApprovalStreamWithRuntime(params))
359
+ }
360
+
361
+ export function createThreadTurnStream(params: ThreadTurnParams) {
362
+ return runPromise(createThreadTurnStreamWithRuntime(params))
363
+ }
364
+
365
+ export function runThreadTurnInBackground(params: ThreadTurnParams): Promise<PreparedThreadTurnResult> {
366
+ return runPromise(runThreadTurnInBackgroundWithRuntime(params))
367
+ }
368
+
369
+ export function triggerPlanNodeTurn(params: {
370
+ runId: string
371
+ nodeId: string
372
+ abortSignal?: AbortSignal
373
+ streamId?: string
374
+ }): Promise<PreparedThreadTurnResult> {
375
+ return runPromise(triggerPlanNodeTurnWithRuntime(params))
376
+ }