@lota-sdk/core 0.4.9 → 0.4.11

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 (182) hide show
  1. package/package.json +2 -2
  2. package/src/ai/embedding-cache.ts +3 -1
  3. package/src/ai-gateway/ai-gateway.ts +164 -82
  4. package/src/ai-gateway/index.ts +16 -1
  5. package/src/config/agent-defaults.ts +4 -107
  6. package/src/config/agent-types.ts +1 -1
  7. package/src/config/background-processing.ts +1 -1
  8. package/src/config/index.ts +0 -1
  9. package/src/config/logger.ts +22 -25
  10. package/src/config/thread-defaults.ts +1 -10
  11. package/src/create-runtime.ts +145 -670
  12. package/src/db/base.service.ts +30 -38
  13. package/src/db/memory-query-builder.ts +2 -1
  14. package/src/db/memory-store.ts +29 -20
  15. package/src/db/memory.ts +188 -195
  16. package/src/db/service-normalization.ts +97 -64
  17. package/src/db/service.ts +496 -384
  18. package/src/db/startup.ts +30 -19
  19. package/src/effect/helpers.ts +30 -5
  20. package/src/effect/index.ts +7 -7
  21. package/src/effect/layers.ts +75 -72
  22. package/src/effect/services.ts +15 -11
  23. package/src/embeddings/provider.ts +65 -71
  24. package/src/index.ts +13 -12
  25. package/src/queues/autonomous-job.queue.ts +177 -143
  26. package/src/queues/context-compaction.queue.ts +41 -39
  27. package/src/queues/delayed-node-promotion.queue.ts +61 -42
  28. package/src/queues/document-processor.queue.ts +5 -3
  29. package/src/queues/index.ts +1 -0
  30. package/src/queues/memory-consolidation.queue.ts +79 -53
  31. package/src/queues/organization-learning.queue.ts +70 -33
  32. package/src/queues/plan-agent-heartbeat.queue.ts +111 -83
  33. package/src/queues/plan-scheduler.queue.ts +101 -97
  34. package/src/queues/post-chat-memory.queue.ts +56 -46
  35. package/src/queues/queue-factory.ts +146 -69
  36. package/src/queues/queues.service.ts +61 -0
  37. package/src/queues/title-generation.queue.ts +44 -44
  38. package/src/redis/connection.ts +181 -164
  39. package/src/redis/org-memory-lock.ts +24 -9
  40. package/src/redis/redis-lease-lock.ts +8 -1
  41. package/src/redis/stream-context.ts +17 -9
  42. package/src/runtime/agent-identity-overrides.ts +7 -3
  43. package/src/runtime/agent-runtime-policy.ts +10 -5
  44. package/src/runtime/agent-stream-helpers.ts +24 -15
  45. package/src/runtime/chat-run-orchestration.ts +1 -1
  46. package/src/runtime/context-compaction/context-compaction-runtime.ts +28 -32
  47. package/src/runtime/context-compaction/context-compaction.ts +131 -85
  48. package/src/runtime/domain-layer.ts +203 -0
  49. package/src/runtime/execution-plan-visibility.ts +5 -2
  50. package/src/runtime/graph-designer.ts +0 -14
  51. package/src/runtime/helper-model.ts +8 -4
  52. package/src/runtime/index.ts +1 -1
  53. package/src/runtime/indexed-repositories-policy.ts +2 -6
  54. package/src/runtime/memory/memory-block.ts +19 -9
  55. package/src/runtime/memory/memory-pipeline.ts +53 -66
  56. package/src/runtime/memory/memory-scope.ts +33 -29
  57. package/src/runtime/plugin-resolution.ts +58 -62
  58. package/src/runtime/post-turn-side-effects.ts +139 -161
  59. package/src/runtime/retrieval-adapters.ts +4 -4
  60. package/src/runtime/runtime-config.ts +3 -9
  61. package/src/runtime/runtime-extensions.ts +0 -43
  62. package/src/runtime/runtime-lifecycle.ts +124 -0
  63. package/src/runtime/runtime-services.ts +455 -0
  64. package/src/runtime/runtime-worker-registry.ts +113 -30
  65. package/src/runtime/social-chat/social-chat-agent-runner.ts +13 -8
  66. package/src/runtime/social-chat/social-chat-history.ts +24 -13
  67. package/src/runtime/social-chat/social-chat.ts +420 -369
  68. package/src/runtime/team-consultation/team-consultation-orchestrator.ts +64 -57
  69. package/src/runtime/team-consultation/team-consultation-prompts.ts +11 -6
  70. package/src/runtime/thread-chat-helpers.ts +18 -9
  71. package/src/runtime/thread-turn-context.ts +28 -74
  72. package/src/runtime/turn-lifecycle.ts +6 -14
  73. package/src/services/agent-activity.service.ts +169 -176
  74. package/src/services/agent-executor.service.ts +207 -196
  75. package/src/services/artifact.service.ts +10 -5
  76. package/src/services/attachment.service.ts +16 -48
  77. package/src/services/autonomous-job.service.ts +81 -87
  78. package/src/services/background-work.service.ts +54 -0
  79. package/src/services/chat-run-registry.service.ts +3 -1
  80. package/src/services/context-compaction.service.ts +8 -10
  81. package/src/services/document-chunk.service.ts +8 -17
  82. package/src/services/execution-plan/execution-plan-graph.ts +122 -109
  83. package/src/services/execution-plan/execution-plan-schedule.ts +1 -15
  84. package/src/services/execution-plan/execution-plan.service.ts +68 -51
  85. package/src/services/feedback-loop.service.ts +1 -1
  86. package/src/services/global-orchestrator.service.ts +49 -15
  87. package/src/services/graph-full-routing.ts +49 -37
  88. package/src/services/index.ts +1 -0
  89. package/src/services/institutional-memory.service.ts +8 -17
  90. package/src/services/learned-skill.service.ts +38 -35
  91. package/src/services/memory/memory-conversation.ts +10 -5
  92. package/src/services/memory/memory-errors.ts +27 -0
  93. package/src/services/memory/memory-org-memory.ts +14 -3
  94. package/src/services/memory/memory-preseeded.ts +10 -4
  95. package/src/services/memory/memory-utils.ts +2 -1
  96. package/src/services/memory/memory.service.ts +37 -52
  97. package/src/services/memory/rerank.service.ts +3 -11
  98. package/src/services/monitoring-window.service.ts +1 -1
  99. package/src/services/mutating-approval.service.ts +1 -1
  100. package/src/services/node-workspace.service.ts +2 -2
  101. package/src/services/notification.service.ts +16 -4
  102. package/src/services/organization-member.service.ts +1 -1
  103. package/src/services/organization.service.ts +34 -51
  104. package/src/services/ownership-dispatcher.service.ts +148 -95
  105. package/src/services/plan/plan-agent-heartbeat.service.ts +30 -16
  106. package/src/services/plan/plan-agent-query.service.ts +13 -9
  107. package/src/services/plan/plan-approval.service.ts +52 -48
  108. package/src/services/plan/plan-artifact.service.ts +2 -2
  109. package/src/services/plan/plan-builder.service.ts +2 -2
  110. package/src/services/plan/plan-checkpoint.service.ts +1 -1
  111. package/src/services/plan/plan-compiler.service.ts +1 -1
  112. package/src/services/plan/plan-completion-side-effects.ts +99 -113
  113. package/src/services/plan/plan-coordination.service.ts +1 -1
  114. package/src/services/plan/plan-cycle.service.ts +171 -202
  115. package/src/services/plan/plan-deadline.service.ts +304 -307
  116. package/src/services/plan/plan-event-delivery.service.ts +84 -72
  117. package/src/services/plan/plan-executor-context.ts +2 -0
  118. package/src/services/plan/plan-executor-graph.ts +375 -353
  119. package/src/services/plan/plan-executor-helpers.ts +60 -75
  120. package/src/services/plan/plan-executor.service.ts +494 -489
  121. package/src/services/plan/plan-run.service.ts +12 -19
  122. package/src/services/plan/plan-scheduler.service.ts +89 -82
  123. package/src/services/plan/plan-template.service.ts +1 -1
  124. package/src/services/plan/plan-transaction-events.ts +8 -5
  125. package/src/services/plan/plan-validator.service.ts +1 -1
  126. package/src/services/plan/plan-workspace.service.ts +17 -11
  127. package/src/services/plugin-executor.service.ts +26 -21
  128. package/src/services/quality-metrics.service.ts +1 -1
  129. package/src/services/queue-job.service.ts +8 -17
  130. package/src/services/recent-activity-title.service.ts +22 -10
  131. package/src/services/recent-activity.service.ts +1 -1
  132. package/src/services/skill-resolver.service.ts +1 -1
  133. package/src/services/social-chat-history.service.ts +37 -20
  134. package/src/services/system-executor.service.ts +25 -20
  135. package/src/services/thread/thread-bootstrap.ts +37 -19
  136. package/src/services/thread/thread-listing.ts +2 -1
  137. package/src/services/thread/thread-memory-block.ts +18 -5
  138. package/src/services/thread/thread-message.service.ts +30 -13
  139. package/src/services/thread/thread-title.service.ts +1 -1
  140. package/src/services/thread/thread-turn-execution.ts +87 -83
  141. package/src/services/thread/thread-turn-preparation.service.ts +65 -40
  142. package/src/services/thread/thread-turn-streaming.ts +32 -36
  143. package/src/services/thread/thread-turn.ts +43 -29
  144. package/src/services/thread/thread.service.ts +32 -8
  145. package/src/services/user.service.ts +1 -1
  146. package/src/services/write-intent-validator.service.ts +1 -1
  147. package/src/storage/attachment-storage.service.ts +7 -4
  148. package/src/storage/generated-document-storage.service.ts +1 -1
  149. package/src/system-agents/context-compaction.agent.ts +1 -1
  150. package/src/system-agents/helper-agent-options.ts +1 -1
  151. package/src/system-agents/memory-reranker.agent.ts +1 -1
  152. package/src/system-agents/memory.agent.ts +1 -1
  153. package/src/system-agents/recent-activity-title-refiner.agent.ts +9 -6
  154. package/src/system-agents/regular-chat-memory-digest.agent.ts +1 -1
  155. package/src/system-agents/skill-extractor.agent.ts +1 -1
  156. package/src/system-agents/skill-manager.agent.ts +1 -1
  157. package/src/system-agents/thread-router.agent.ts +23 -20
  158. package/src/system-agents/title-generator.agent.ts +1 -1
  159. package/src/tools/execution-plan.tool.ts +36 -20
  160. package/src/tools/fetch-webpage.tool.ts +30 -22
  161. package/src/tools/firecrawl-client.ts +1 -6
  162. package/src/tools/plan-approval.tool.ts +9 -1
  163. package/src/tools/remember-memory.tool.ts +3 -6
  164. package/src/tools/research-topic.tool.ts +12 -3
  165. package/src/tools/search-web.tool.ts +26 -18
  166. package/src/tools/search.tool.ts +4 -5
  167. package/src/tools/team-think.tool.ts +139 -121
  168. package/src/utils/async.ts +15 -6
  169. package/src/utils/errors.ts +27 -15
  170. package/src/workers/bootstrap.ts +34 -58
  171. package/src/workers/memory-consolidation.worker.ts +4 -1
  172. package/src/workers/organization-learning.worker.ts +16 -3
  173. package/src/workers/regular-chat-memory-digest.helpers.ts +3 -4
  174. package/src/workers/regular-chat-memory-digest.runner.ts +46 -29
  175. package/src/workers/skill-extraction.runner.ts +13 -15
  176. package/src/workers/worker-utils.ts +14 -8
  177. package/src/config/search.ts +0 -3
  178. package/src/effect/awaitable-effect.ts +0 -87
  179. package/src/effect/runtime-ref.ts +0 -25
  180. package/src/effect/runtime.ts +0 -31
  181. package/src/redis/runtime-connection.ts +0 -10
  182. package/src/runtime/agent-types.ts +0 -1
@@ -1,281 +1,65 @@
1
- import type { ChatMessage } from '@lota-sdk/shared'
2
- import type { Context } from 'effect'
3
- import { Effect, Layer, ManagedRuntime } from 'effect'
4
- import { DevTools } from 'effect/unstable/devtools'
5
- import { FetchHttpClient } from 'effect/unstable/http'
6
- import { Otlp } from 'effect/unstable/observability'
1
+ import type { Fiber } from 'effect'
2
+ import { Effect, ManagedRuntime } from 'effect'
7
3
  import type { Subscriber } from 'resumable-stream/ioredis'
8
4
 
9
- import { AiGatewayLive } from './ai-gateway/ai-gateway'
10
- import { EmbeddingCacheLive } from './ai/embedding-cache'
11
- import { ensureRecordId } from './db/record-id'
5
+ import { AiGatewayTag, bindAiGatewayRuntime } from './ai-gateway/ai-gateway'
12
6
  import { computeSchemaFingerprint } from './db/schema-fingerprint'
13
- import type { SurrealDBService } from './db/service'
14
7
  import { publishDatabaseBootstrapEffect } from './db/startup'
15
- import { TABLES } from './db/tables'
16
8
  import {
9
+ AgentConfigServiceTag,
10
+ AgentFactoryServiceTag,
17
11
  buildInfrastructureLayer,
18
- clearLotaSdkRuntime,
19
12
  DatabaseServiceTag as EffectDatabaseService,
20
13
  RedisServiceTag as EffectRedisService,
21
- runPromise,
22
- setLotaSdkRuntime,
14
+ RuntimeAdaptersServiceTag,
15
+ RuntimeConfigServiceTag,
23
16
  } from './effect'
24
- import type { AwaitableService, AwaitableValue } from './effect/awaitable-effect'
25
- import { toAwaitableService } from './effect/awaitable-effect'
26
- import { BadRequestError, ConfigurationError, NotFoundError, ServiceError } from './effect/errors'
17
+ import { ConfigurationError, ServiceError } from './effect/errors'
27
18
  import { effectTryPromise } from './effect/helpers'
19
+ import { LotaQueuesServiceTag } from './queues/queues.service'
28
20
  import type { RedisConnectionManager } from './redis/connection'
29
- import { SharedThreadStreamSubscriberLive, SharedThreadStreamSubscriberTag } from './redis/stream-context'
30
- import type { isApprovalContinuationRequest } from './runtime/approval-continuation'
31
- import { routeThreadChatMessages } from './runtime/chat-request-routing'
32
- import { CompactionCoordinationLive } from './runtime/chat-run-orchestration'
33
- import { HelperModelLive } from './runtime/helper-model'
34
- import type { LotaPlugin, PluginLifecycleServices, SystemNodeExecutor } from './runtime/plugin-types'
21
+ import { SharedThreadStreamSubscriberTag } from './redis/stream-context'
22
+ import { buildDomainServiceLayer } from './runtime/domain-layer'
23
+ import type { LotaPlugin, SystemNodeExecutor } from './runtime/plugin-types'
35
24
  import { LOTA_RUNTIME_ENV_KEYS, loadLotaRuntimeConfigFromEnv, parseLotaRuntimeConfig } from './runtime/runtime-config'
36
25
  import type { LotaRuntimeConfig, ResolvedLotaRuntimeConfig } from './runtime/runtime-config'
26
+ import {
27
+ createPluginDatabaseConnector,
28
+ createPluginDatabaseDisconnector,
29
+ createRuntimeDisconnect,
30
+ } from './runtime/runtime-lifecycle'
31
+ import { buildRuntimeServiceSurface } from './runtime/runtime-services'
32
+ import type { LotaRuntimeLota, LotaRuntimeServices } from './runtime/runtime-services'
37
33
  import type { LotaRuntimeWorkers } from './runtime/runtime-worker-registry'
38
34
  import { buildRuntimeWorkerRegistry } from './runtime/runtime-worker-registry'
39
35
  import type { LotaRuntimeSocialChat } from './runtime/social-chat/social-chat'
40
36
  import { createSocialChatRuntime } from './runtime/social-chat/social-chat'
41
- // ── Service Layer & Tag imports ────────────────────────────────────────
42
- import { AgentActivityServiceLive, AgentActivityServiceTag } from './services/agent-activity.service'
43
- import { AgentExecutorServiceLive } from './services/agent-executor.service'
44
- import { ArtifactServiceLive, ArtifactServiceTag } from './services/artifact.service'
45
- import { AttachmentServiceLive, AttachmentServiceTag } from './services/attachment.service'
46
- import { AutonomousJobServiceLive, AutonomousJobServiceTag } from './services/autonomous-job.service'
47
- import { ChatRunRegistryLive } from './services/chat-run-registry.service'
48
- import { ContextCompactionServiceLive, ContextCompactionServiceTag } from './services/context-compaction.service'
49
- import { DocumentChunkServiceLive, DocumentChunkServiceTag } from './services/document-chunk.service'
50
- import { ExecutionPlanServiceLive, ExecutionPlanServiceTag } from './services/execution-plan/execution-plan.service'
51
- import { FeedbackLoopServiceLive } from './services/feedback-loop.service'
52
- import { GlobalOrchestratorServiceLive } from './services/global-orchestrator.service'
53
- import { InstitutionalMemoryServiceLive } from './services/institutional-memory.service'
54
- import { LearnedSkillServiceLive, LearnedSkillServiceTag } from './services/learned-skill.service'
55
- import { MemoryServiceLive, MemoryServiceTag } from './services/memory/memory.service'
56
- import { RerankServiceLive, RerankServiceTag } from './services/memory/rerank.service'
57
- import { MonitoringWindowServiceLive } from './services/monitoring-window.service'
58
- import { MutatingApprovalServiceLive, MutatingApprovalServiceTag } from './services/mutating-approval.service'
59
- import { NodeWorkspaceServiceLive } from './services/node-workspace.service'
60
- import { NotificationServiceLive } from './services/notification.service'
61
- import { OrganizationMemberServiceLive, OrganizationMemberServiceTag } from './services/organization-member.service'
62
- import { OrganizationServiceLive, OrganizationServiceTag } from './services/organization.service'
63
- import { OwnershipDispatcherServiceLive } from './services/ownership-dispatcher.service'
64
- import {
65
- PlanAgentHeartbeatServiceLive,
66
- PlanAgentHeartbeatServiceTag,
67
- } from './services/plan/plan-agent-heartbeat.service'
68
- import { PlanAgentQueryServiceLive, PlanAgentQueryServiceTag } from './services/plan/plan-agent-query.service'
69
- import { PlanApprovalServiceLive } from './services/plan/plan-approval.service'
70
- import { PlanArtifactServiceLive } from './services/plan/plan-artifact.service'
71
- import { PlanBuilderServiceLive } from './services/plan/plan-builder.service'
72
- import { PlanCheckpointServiceLive } from './services/plan/plan-checkpoint.service'
73
- import { PlanCompilerServiceLive } from './services/plan/plan-compiler.service'
74
- import { PlanCoordinationServiceLive, PlanCoordinationServiceTag } from './services/plan/plan-coordination.service'
75
- import { PlanCycleServiceLive, PlanCycleServiceTag } from './services/plan/plan-cycle.service'
76
- import { PlanDeadlineServiceLive, PlanDeadlineServiceTag } from './services/plan/plan-deadline.service'
77
- import { PlanEventDeliveryServiceLive } from './services/plan/plan-event-delivery.service'
78
- import { PlanExecutorServiceLive, PlanExecutorServiceTag } from './services/plan/plan-executor.service'
79
- import { PlanRunServiceLive, PlanRunServiceTag } from './services/plan/plan-run.service'
80
- import { PlanSchedulerServiceLive, PlanSchedulerServiceTag } from './services/plan/plan-scheduler.service'
81
- import { PlanTemplateServiceLive, PlanTemplateServiceTag } from './services/plan/plan-template.service'
82
- import { PlanValidatorServiceLive } from './services/plan/plan-validator.service'
83
- import { PlanWorkspaceServiceLive } from './services/plan/plan-workspace.service'
84
- import { PluginExecutorServiceLive } from './services/plugin-executor.service'
85
- import { QualityMetricsServiceLive } from './services/quality-metrics.service'
86
- import { QueueJobServiceLive } from './services/queue-job.service'
87
- import { RecentActivityTitleServiceLive, RecentActivityTitleServiceTag } from './services/recent-activity-title.service'
88
- import { RecentActivityServiceLive, RecentActivityServiceTag } from './services/recent-activity.service'
89
- import { SkillResolverServiceLive } from './services/skill-resolver.service'
90
- import type { makeSocialChatHistoryService } from './services/social-chat-history.service'
91
- import { SocialChatHistoryServiceLive, SocialChatHistoryServiceTag } from './services/social-chat-history.service'
92
- import { getBuiltInSystemExecutors, SystemExecutorServiceLive } from './services/system-executor.service'
93
- import { ThreadMessageServiceLive, ThreadMessageServiceTag } from './services/thread/thread-message.service'
94
- import { ThreadTitleServiceLive, ThreadTitleServiceTag } from './services/thread/thread-title.service'
95
- import type {
96
- createThreadApprovalContinuationStream,
97
- createThreadNativeToolApprovalStream,
98
- createThreadTurnStream,
99
- runThreadTurnInBackground,
100
- triggerPlanNodeTurn,
101
- } from './services/thread/thread-turn'
102
- import {
103
- isApprovalContinuationRequest as isApprovalContinuationRequestFn,
104
- ThreadTurnServiceLive,
105
- ThreadTurnServiceTag,
106
- } from './services/thread/thread-turn'
107
- import { ThreadTurnPreparationServiceLive } from './services/thread/thread-turn-preparation.service'
108
- import { ThreadServiceLive, ThreadServiceTag } from './services/thread/thread.service'
109
- import { UserServiceLive, UserServiceTag } from './services/user.service'
110
- import { WriteIntentValidatorServiceLive } from './services/write-intent-validator.service'
111
- import { AttachmentStorageServiceLive } from './storage/attachment-storage.service'
112
- import {
113
- GeneratedDocumentStorageServiceLive,
114
- GeneratedDocumentStorageServiceTag,
115
- } from './storage/generated-document-storage.service'
116
- import { FirecrawlLive } from './tools/firecrawl-client'
117
-
118
- // ── Type helpers ────────────────────────────────────────────────────────
119
- type Svc<T extends { readonly Service: unknown }> = T['Service']
120
- type HostSvc<T extends { readonly Service: object }> = AwaitableService<T['Service']>
121
- type AwaitableThreadService = HostSvc<typeof ThreadServiceTag> &
122
- Pick<Svc<typeof ThreadServiceTag>, 'withActiveRunLease'>
123
- type AwaitableDocumentChunkService = HostSvc<typeof DocumentChunkServiceTag> &
124
- Pick<Svc<typeof DocumentChunkServiceTag>, 'syncVersionedChunks'>
125
-
126
- type ArchiveSdkThread = (
127
- threadId: Parameters<Svc<typeof ThreadServiceTag>['updateStatus']>[0],
128
- status?: 'archived',
129
- ) => ReturnType<Svc<typeof ThreadServiceTag>['updateStatus']>
130
-
131
- type UnarchiveSdkThread = (
132
- threadId: Parameters<Svc<typeof ThreadServiceTag>['updateStatus']>[0],
133
- status?: 'active',
134
- ) => ReturnType<Svc<typeof ThreadServiceTag>['updateStatus']>
135
-
136
- let activeRuntimeToken: symbol | null = null
137
-
138
- function claimRuntimeToken(): Effect.Effect<symbol, ConfigurationError> {
139
- return Effect.gen(function* () {
140
- if (activeRuntimeToken) {
141
- return yield* new ConfigurationError({
142
- message: 'createLotaRuntime() is process-scoped. Disconnect the active runtime before creating another one.',
143
- })
144
- }
145
-
146
- const token = Symbol('lota-runtime')
147
- activeRuntimeToken = token
148
- return token
149
- })
150
- }
151
-
152
- function releaseRuntimeToken(token: symbol) {
153
- if (activeRuntimeToken === token) {
154
- activeRuntimeToken = null
155
- }
156
- }
157
-
158
- function buildObservabilityLayer(runtimeConfig: ResolvedLotaRuntimeConfig): Layer.Layer<never> {
159
- let layer = Layer.empty
160
- const observability = runtimeConfig.observability
161
-
162
- if (observability.otlpBaseUrl) {
163
- layer = Layer.merge(
164
- layer,
165
- Otlp.layerJson({
166
- baseUrl: observability.otlpBaseUrl,
167
- resource: {
168
- serviceName: observability.serviceName,
169
- ...(observability.serviceVersion ? { serviceVersion: observability.serviceVersion } : {}),
170
- },
171
- ...(observability.otlpHeaders ? { headers: observability.otlpHeaders } : {}),
172
- }).pipe(Layer.provide(FetchHttpClient.layer)),
173
- )
174
- }
175
-
176
- if (observability.devToolsUrl && Bun.env.NODE_ENV !== 'production') {
177
- layer = Layer.merge(layer, DevTools.layer(observability.devToolsUrl))
178
- }
179
-
180
- return layer
181
- }
37
+ import { AutonomousJobServiceTag } from './services/autonomous-job.service'
38
+ import { ContextCompactionServiceTag } from './services/context-compaction.service'
39
+ import { LearnedSkillServiceTag } from './services/learned-skill.service'
40
+ import { MemoryServiceTag } from './services/memory/memory.service'
41
+ import { PlanAgentHeartbeatServiceTag } from './services/plan/plan-agent-heartbeat.service'
42
+ import { PlanCycleServiceTag } from './services/plan/plan-cycle.service'
43
+ import { PlanDeadlineServiceTag } from './services/plan/plan-deadline.service'
44
+ import { PlanExecutorServiceTag } from './services/plan/plan-executor.service'
45
+ import { PlanSchedulerServiceTag } from './services/plan/plan-scheduler.service'
46
+ import { RecentActivityTitleServiceTag } from './services/recent-activity-title.service'
47
+ import { SocialChatHistoryServiceTag } from './services/social-chat-history.service'
48
+ import { getBuiltInSystemExecutors } from './services/system-executor.service'
49
+ import { ThreadTitleServiceTag } from './services/thread/thread-title.service'
50
+ import { ThreadTurnServiceTag } from './services/thread/thread-turn'
51
+ import { ThreadServiceTag } from './services/thread/thread.service'
182
52
 
183
53
  export interface LotaRuntime {
184
54
  /** Run an Effect as a Promise through the SDK runtime (carries OTLP context). */
185
- runPromise: <A, E>(effect: Effect.Effect<A, E>, options?: { readonly signal?: AbortSignal }) => Promise<A>
55
+ runPromise: <A, E, R>(effect: Effect.Effect<A, E, R>, options?: { readonly signal?: AbortSignal }) => Promise<A>
186
56
  /** Run an Effect synchronously through the SDK runtime. */
187
- runSync: <A, E>(effect: Effect.Effect<A, E>) => A
188
- services: {
189
- database: SurrealDBService
190
- redis: RedisConnectionManager
191
- closeRedisConnection: () => Promise<void>
192
- agentActivityService: HostSvc<typeof AgentActivityServiceTag>
193
- artifactService: HostSvc<typeof ArtifactServiceTag>
194
- attachmentService: HostSvc<typeof AttachmentServiceTag>
195
- autonomousJobService: HostSvc<typeof AutonomousJobServiceTag>
196
- contextCompactionService: HostSvc<typeof ContextCompactionServiceTag>
197
- documentChunkService: AwaitableDocumentChunkService
198
- generatedDocumentStorageService: HostSvc<typeof GeneratedDocumentStorageServiceTag>
199
- memoryService: HostSvc<typeof MemoryServiceTag>
200
- rerankService: HostSvc<typeof RerankServiceTag>
201
- verifyMutatingApproval: HostSvc<typeof MutatingApprovalServiceTag>
202
- organizationService: HostSvc<typeof OrganizationServiceTag>
203
- organizationMemberService: HostSvc<typeof OrganizationMemberServiceTag>
204
- userService: HostSvc<typeof UserServiceTag>
205
- recentActivityService: HostSvc<typeof RecentActivityServiceTag>
206
- recentActivityTitleService: HostSvc<typeof RecentActivityTitleServiceTag>
207
- socialChatHistoryService: ReturnType<typeof makeSocialChatHistoryService>
208
- executionPlanService: HostSvc<typeof ExecutionPlanServiceTag>
209
- planDeadlineService: HostSvc<typeof PlanDeadlineServiceTag>
210
- planExecutorService: HostSvc<typeof PlanExecutorServiceTag>
211
- planRunService: HostSvc<typeof PlanRunServiceTag>
212
- planTemplateService: HostSvc<typeof PlanTemplateServiceTag>
213
- planCoordinationService: HostSvc<typeof PlanCoordinationServiceTag>
214
- planSchedulerService: HostSvc<typeof PlanSchedulerServiceTag>
215
- planAgentHeartbeatService: HostSvc<typeof PlanAgentHeartbeatServiceTag>
216
- planAgentQueryService: HostSvc<typeof PlanAgentQueryServiceTag>
217
- planCycleService: HostSvc<typeof PlanCycleServiceTag>
218
- threadMessageService: HostSvc<typeof ThreadMessageServiceTag>
219
- threadService: AwaitableThreadService
220
- threadTitleService: HostSvc<typeof ThreadTitleServiceTag>
221
- createThreadApprovalContinuationStream: typeof createThreadApprovalContinuationStream
222
- createThreadNativeToolApprovalStream: typeof createThreadNativeToolApprovalStream
223
- createThreadTurnStream: typeof createThreadTurnStream
224
- isApprovalContinuationRequest: typeof isApprovalContinuationRequest
225
- runThreadTurnInBackground: typeof runThreadTurnInBackground
226
- triggerPlanNodeTurn: typeof triggerPlanNodeTurn
227
- }
228
- lota: {
229
- organizations: {
230
- create: AwaitableValue<Svc<typeof OrganizationServiceTag>['createOrganization']>
231
- upsert: AwaitableValue<Svc<typeof OrganizationServiceTag>['upsertOrganization']>
232
- get: AwaitableValue<Svc<typeof OrganizationServiceTag>['getOrganization']>
233
- list: AwaitableValue<Svc<typeof OrganizationServiceTag>['listOrganizations']>
234
- update: AwaitableValue<Svc<typeof OrganizationServiceTag>['updateOrganization']>
235
- delete: AwaitableValue<Svc<typeof OrganizationServiceTag>['deleteOrganization']>
236
- }
237
- users: {
238
- upsert: AwaitableValue<Svc<typeof UserServiceTag>['upsertUser']>
239
- get: AwaitableValue<Svc<typeof UserServiceTag>['getUser']>
240
- list: AwaitableValue<Svc<typeof UserServiceTag>['listUsers']>
241
- update: AwaitableValue<Svc<typeof UserServiceTag>['updateUser']>
242
- delete: AwaitableValue<Svc<typeof UserServiceTag>['deleteUser']>
243
- }
244
- memberships: {
245
- add: AwaitableValue<Svc<typeof OrganizationMemberServiceTag>['addMembership']>
246
- listForOrganization: AwaitableValue<Svc<typeof OrganizationMemberServiceTag>['listMembershipsForOrganization']>
247
- listForUser: AwaitableValue<Svc<typeof OrganizationMemberServiceTag>['listMembershipsForUser']>
248
- remove: AwaitableValue<Svc<typeof OrganizationMemberServiceTag>['removeMembership']>
249
- isMember: AwaitableValue<Svc<typeof OrganizationMemberServiceTag>['isMember']>
250
- }
251
- threads: {
252
- create: AwaitableValue<Svc<typeof ThreadServiceTag>['createThread']>
253
- list: AwaitableValue<Svc<typeof ThreadServiceTag>['listThreads']>
254
- get: AwaitableValue<Svc<typeof ThreadServiceTag>['getThread']>
255
- update: AwaitableValue<Svc<typeof ThreadServiceTag>['updateTitle']>
256
- archive: AwaitableValue<ArchiveSdkThread>
257
- unarchive: AwaitableValue<UnarchiveSdkThread>
258
- delete: AwaitableValue<Svc<typeof ThreadServiceTag>['deleteThread']>
259
- stop: AwaitableValue<Svc<typeof ThreadServiceTag>['stopActiveRun']>
260
- listMessages: AwaitableValue<Svc<typeof ThreadMessageServiceTag>['listMessageHistoryPage']>
261
- getMessage: (params: { threadId: string; messageId: string }) => Promise<ChatMessage>
262
- sendMessage: (params: {
263
- threadId: string
264
- organizationId: string
265
- userId: string
266
- userName: string
267
- messages: Parameters<typeof routeThreadChatMessages>[0]
268
- }) => Promise<Awaited<ReturnType<typeof createThreadTurnStream>>>
269
- continueApproval: (params: {
270
- threadId: string
271
- organizationId: string
272
- userId: string
273
- userName: string
274
- messages: Parameters<typeof routeThreadChatMessages>[0]
275
- }) => Promise<Awaited<ReturnType<typeof createThreadApprovalContinuationStream>>>
276
- uploadAttachment: AwaitableValue<Svc<typeof AttachmentServiceTag>['uploadThreadAttachment']>
277
- }
278
- }
57
+ runSync: <A, E, R>(effect: Effect.Effect<A, E, R>) => A
58
+ /** Fork an Effect as a Fiber through the SDK runtime (carries OTLP context). */
59
+ // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents
60
+ runFork: <A, E, R>(effect: Effect.Effect<A, E, R>) => Fiber.Fiber<A, E | unknown>
61
+ services: LotaRuntimeServices
62
+ lota: LotaRuntimeLota
279
63
  redis: {
280
64
  manager: RedisConnectionManager
281
65
  subscriber: Subscriber
@@ -305,12 +89,10 @@ export function createLotaRuntimeFromEnv(
305
89
  }
306
90
 
307
91
  export function createLotaRuntime(config: LotaRuntimeConfig): Promise<LotaRuntime> {
308
- let runtimeToken: symbol | null = null
309
92
  let effectRuntime: { dispose(): Promise<void> } | null = null
310
93
 
311
94
  return Effect.runPromise(
312
95
  Effect.gen(function* () {
313
- runtimeToken = yield* claimRuntimeToken()
314
96
  const resolvedConfig = parseLotaRuntimeConfig(config)
315
97
  const systemExecutors = { ...getBuiltInSystemExecutors(), ...resolvedConfig.systemExecutors }
316
98
  const runtimeConfig = { ...resolvedConfig, systemExecutors } satisfies ResolvedLotaRuntimeConfig
@@ -327,121 +109,14 @@ export function createLotaRuntime(config: LotaRuntimeConfig): Promise<LotaRuntim
327
109
  ? { ...runtimeConfig.agents.displayNames, [socialChatAgentId]: socialChatAgentDisplayName }
328
110
  : runtimeConfig.agents.displayNames
329
111
 
330
- // ── Infrastructure layers ───────────────────────────────────────────
331
- const infrastructureLayer = buildInfrastructureLayer(runtimeConfig, {
332
- resolvedAgentDisplayNames,
333
- observabilityLayer: buildObservabilityLayer(runtimeConfig),
334
- })
335
-
336
- // ── Domain service layers ───────────────────────────────────────────
337
- function provide<A, E, R extends RCtx, RCtx, E2>(
338
- layer: Layer.Layer<A, E, R>,
339
- ctx: Layer.Layer<RCtx, E2, never>,
340
- ): Layer.Layer<A, E | E2, never> {
341
- return Layer.provideMerge(ctx)(layer)
342
- }
343
-
344
- const tier0 = provide(
345
- Layer.mergeAll(
346
- ChatRunRegistryLive,
347
- CompactionCoordinationLive,
348
- DocumentChunkServiceLive,
349
- NodeWorkspaceServiceLive,
350
- NotificationServiceLive,
351
- PlanArtifactServiceLive,
352
- PlanBuilderServiceLive,
353
- WriteIntentValidatorServiceLive,
354
- ),
355
- infrastructureLayer,
356
- )
357
- const ctx0 = Layer.mergeAll(
358
- infrastructureLayer,
359
- provide(Layer.mergeAll(AiGatewayLive, EmbeddingCacheLive, FirecrawlLive, HelperModelLive), infrastructureLayer),
360
- tier0,
361
- )
362
-
363
- const tier1 = provide(
364
- Layer.mergeAll(
365
- SharedThreadStreamSubscriberLive,
366
- AgentExecutorServiceLive,
367
- AttachmentStorageServiceLive,
368
- GeneratedDocumentStorageServiceLive,
369
- LearnedSkillServiceLive,
370
- OrganizationServiceLive,
371
- OrganizationMemberServiceLive,
372
- PlanApprovalServiceLive,
373
- PlanRunServiceLive,
374
- PlanSchedulerServiceLive,
375
- PlanWorkspaceServiceLive,
376
- PluginExecutorServiceLive,
377
- QualityMetricsServiceLive,
378
- QueueJobServiceLive,
379
- RecentActivityServiceLive,
380
- RerankServiceLive,
381
- SocialChatHistoryServiceLive,
382
- SystemExecutorServiceLive,
383
- ThreadMessageServiceLive,
384
- UserServiceLive,
385
- ),
386
- ctx0,
387
- )
388
- const ctx1 = Layer.mergeAll(ctx0, tier1)
389
-
390
- const tier2 = provide(
391
- Layer.mergeAll(
392
- ArtifactServiceLive,
393
- AttachmentServiceLive,
394
- ContextCompactionServiceLive,
395
- FeedbackLoopServiceLive,
396
- InstitutionalMemoryServiceLive,
397
- MemoryServiceLive,
398
- MonitoringWindowServiceLive,
399
- MutatingApprovalServiceLive,
400
- PlanAgentQueryServiceLive,
401
- PlanCheckpointServiceLive,
402
- PlanCoordinationServiceLive,
403
- PlanEventDeliveryServiceLive,
404
- SkillResolverServiceLive,
405
- RecentActivityTitleServiceLive,
406
- ),
407
- ctx1,
408
- )
409
- const ctx2 = Layer.mergeAll(ctx1, tier2)
410
-
411
- const tier3 = provide(Layer.mergeAll(PlanValidatorServiceLive, ThreadServiceLive), ctx2)
412
- const ctx3 = Layer.mergeAll(ctx2, tier3)
413
-
414
- const tier4 = provide(Layer.mergeAll(PlanCompilerServiceLive, ThreadTitleServiceLive), ctx3)
415
- const ctx4 = Layer.mergeAll(ctx3, tier4)
416
-
417
- const tier5 = provide(PlanExecutorServiceLive, ctx4)
418
- const ctx5 = Layer.mergeAll(ctx4, tier5)
419
-
420
- const tier6 = provide(
421
- Layer.mergeAll(OwnershipDispatcherServiceLive, PlanAgentHeartbeatServiceLive, PlanDeadlineServiceLive),
422
- ctx5,
423
- )
424
- const ctx6 = Layer.mergeAll(ctx5, tier6)
425
-
426
- const tier7 = provide(Layer.mergeAll(ExecutionPlanServiceLive, GlobalOrchestratorServiceLive), ctx6)
427
- const ctx7 = Layer.mergeAll(ctx6, tier7)
428
-
429
- const tier8 = provide(
430
- Layer.mergeAll(
431
- PlanTemplateServiceLive,
432
- AutonomousJobServiceLive,
433
- AgentActivityServiceLive,
434
- ThreadTurnPreparationServiceLive,
435
- ),
436
- ctx7,
437
- )
438
- const ctx8 = Layer.mergeAll(ctx7, tier8)
439
-
440
- const tier9 = provide(Layer.mergeAll(PlanCycleServiceLive, ThreadTurnServiceLive), ctx8)
441
- const fullLayer = Layer.mergeAll(ctx8, tier9)
112
+ // ── Infrastructure + domain layer composition ─────────────────────
113
+ const infrastructureLayer = buildInfrastructureLayer(runtimeConfig, { resolvedAgentDisplayNames })
114
+ const fullLayer = buildDomainServiceLayer(infrastructureLayer)
442
115
 
443
116
  const managedRuntime = ManagedRuntime.make(fullLayer)
444
117
  effectRuntime = managedRuntime
118
+
119
+ // Eagerly resolve the services the outer entrypoint needs directly.
445
120
  const resolvedServices = yield* Effect.tryPromise({
446
121
  try: () =>
447
122
  managedRuntime.runPromise(
@@ -454,6 +129,22 @@ export function createLotaRuntime(config: LotaRuntimeConfig): Promise<LotaRuntim
454
129
  socialChatHistoryService: yield* SocialChatHistoryServiceTag,
455
130
  learnedSkillService: yield* LearnedSkillServiceTag,
456
131
  memoryService: yield* MemoryServiceTag,
132
+ runtimeAdapters: yield* RuntimeAdaptersServiceTag,
133
+ agentConfig: yield* AgentConfigServiceTag,
134
+ agentFactoryConfig: yield* AgentFactoryServiceTag,
135
+ queues: yield* LotaQueuesServiceTag,
136
+ autonomousJobService: yield* AutonomousJobServiceTag,
137
+ contextCompactionService: yield* ContextCompactionServiceTag,
138
+ threadService: yield* ThreadServiceTag,
139
+ planAgentHeartbeatService: yield* PlanAgentHeartbeatServiceTag,
140
+ planSchedulerService: yield* PlanSchedulerServiceTag,
141
+ planDeadlineService: yield* PlanDeadlineServiceTag,
142
+ planExecutorService: yield* PlanExecutorServiceTag,
143
+ planCycleService: yield* PlanCycleServiceTag,
144
+ threadTitleService: yield* ThreadTitleServiceTag,
145
+ recentActivityTitleService: yield* RecentActivityTitleServiceTag,
146
+ aiGateway: yield* AiGatewayTag,
147
+ runtimeConfigService: yield* RuntimeConfigServiceTag,
457
148
  }
458
149
  }),
459
150
  ),
@@ -471,18 +162,34 @@ export function createLotaRuntime(config: LotaRuntimeConfig): Promise<LotaRuntim
471
162
  socialChatHistoryService,
472
163
  learnedSkillService,
473
164
  memoryService,
165
+ runtimeAdapters,
166
+ agentConfig,
167
+ agentFactoryConfig,
168
+ queues,
169
+ autonomousJobService,
170
+ contextCompactionService,
171
+ threadService,
172
+ planAgentHeartbeatService,
173
+ planSchedulerService,
174
+ planDeadlineService,
175
+ planExecutorService,
176
+ planCycleService,
177
+ threadTitleService,
178
+ recentActivityTitleService,
179
+ aiGateway,
180
+ runtimeConfigService,
474
181
  } = resolvedServices
475
182
 
476
- setLotaSdkRuntime(managedRuntime)
477
-
478
- type RuntimeServices = Layer.Success<typeof fullLayer>
479
- const resolve = <I extends RuntimeServices, T>(tag: Context.Key<I, T>): T =>
480
- managedRuntime.runSync(Effect.service(tag))
481
- const resolveAwaitableService = <I extends RuntimeServices, T extends object>(
482
- tag: Context.Key<I, T>,
483
- ): AwaitableService<T> =>
484
- toAwaitableService(resolve(tag), { runPromise: (effect) => managedRuntime.runPromise(effect) })
183
+ // Seed the AI gateway middleware so wrapGenerate/wrapStream/wrapEmbed
184
+ // edges can run Effects without reaching for an ambient runtime slot.
185
+ bindAiGatewayRuntime({
186
+ gateway: aiGateway,
187
+ runtimeConfig: runtimeConfigService,
188
+ runPromise: (effect) => managedRuntime.runPromise(effect),
189
+ runFork: (effect) => managedRuntime.runFork(effect),
190
+ })
485
191
 
192
+ // ── Schema + plugin + worker + social-chat composition ────────────
486
193
  const pluginRuntime = runtimeConfig.pluginRuntime ?? {}
487
194
  const pluginContributions = Object.values(pluginRuntime).map((plugin) => plugin.contributions)
488
195
  const hostContributionSchemaFiles = pluginContributions.flatMap((plugin) => plugin.schemaFiles)
@@ -493,224 +200,71 @@ export function createLotaRuntime(config: LotaRuntimeConfig): Promise<LotaRuntim
493
200
  ]
494
201
  const contributionEnvKeys = [...LOTA_RUNTIME_ENV_KEYS, ...pluginContributions.flatMap((plugin) => plugin.envKeys)]
495
202
  const connectedPluginDatabases = new Set<string>()
496
- const connectPluginDatabases = createPluginDatabaseConnector(pluginRuntime, connectedPluginDatabases)
497
- const disconnectPluginDatabases = createPluginDatabaseDisconnector(pluginRuntime, connectedPluginDatabases)
498
- const workers = buildRuntimeWorkerRegistry(runtimeConfig.extraWorkers)
203
+ const connectPluginDatabases = createPluginDatabaseConnector(
204
+ managedRuntime,
205
+ pluginRuntime,
206
+ connectedPluginDatabases,
207
+ )
208
+ const disconnectPluginDatabases = createPluginDatabaseDisconnector(
209
+ managedRuntime,
210
+ pluginRuntime,
211
+ connectedPluginDatabases,
212
+ )
213
+ const workers = buildRuntimeWorkerRegistry(
214
+ queues,
215
+ {
216
+ databaseService: db,
217
+ threadService,
218
+ contextCompactionService,
219
+ autonomousJobService,
220
+ memoryService,
221
+ planAgentHeartbeatService,
222
+ planSchedulerService,
223
+ planDeadlineService,
224
+ planExecutorService,
225
+ planCycleService,
226
+ threadTitleService,
227
+ recentActivityTitleService,
228
+ redisManager,
229
+ },
230
+ runtimeConfig.extraWorkers,
231
+ )
499
232
  const socialChat = createSocialChatRuntime({
233
+ agentConfig,
234
+ agentFactoryConfig,
500
235
  redisClient: redisManager.getConnection() as unknown as Parameters<
501
236
  typeof createSocialChatRuntime
502
237
  >[0]['redisClient'],
503
238
  socialChat: runtimeConfig.socialChat,
504
- services: { learnedSkillService, memoryService, socialChatHistoryService },
239
+ services: { learnedSkillService, memoryService, socialChatHistoryService, runtimeAdapters, queues },
505
240
  })
241
+ const currentContext = yield* Effect.context()
242
+ const runPromiseWithCurrentContext = Effect.runPromiseWith(currentContext)
506
243
 
507
- const services: LotaRuntime['services'] = {
508
- database: db,
509
- redis: redisManager,
510
- closeRedisConnection: () => runPromise(effectTryPromise(() => redisManager.closeConnection())),
511
- get agentActivityService() {
512
- return resolveAwaitableService(AgentActivityServiceTag)
513
- },
514
- get artifactService() {
515
- return resolveAwaitableService(ArtifactServiceTag)
516
- },
517
- get attachmentService() {
518
- return resolveAwaitableService(AttachmentServiceTag)
519
- },
520
- get autonomousJobService() {
521
- return resolveAwaitableService(AutonomousJobServiceTag)
522
- },
523
- get contextCompactionService() {
524
- return resolveAwaitableService(ContextCompactionServiceTag)
525
- },
526
- get documentChunkService() {
527
- return resolveAwaitableService(DocumentChunkServiceTag) as AwaitableDocumentChunkService
528
- },
529
- get generatedDocumentStorageService() {
530
- return resolveAwaitableService(GeneratedDocumentStorageServiceTag)
531
- },
532
- get memoryService() {
533
- return resolveAwaitableService(MemoryServiceTag)
534
- },
535
- get rerankService() {
536
- return resolveAwaitableService(RerankServiceTag)
537
- },
538
- get verifyMutatingApproval() {
539
- return resolveAwaitableService(MutatingApprovalServiceTag)
540
- },
541
- get organizationService() {
542
- return resolveAwaitableService(OrganizationServiceTag)
543
- },
544
- get organizationMemberService() {
545
- return resolveAwaitableService(OrganizationMemberServiceTag)
546
- },
547
- get userService() {
548
- return resolveAwaitableService(UserServiceTag)
549
- },
550
- get recentActivityService() {
551
- return resolveAwaitableService(RecentActivityServiceTag)
552
- },
553
- get recentActivityTitleService() {
554
- return resolveAwaitableService(RecentActivityTitleServiceTag)
555
- },
244
+ // ── Service surface (eager, plain-property) ───────────────────────
245
+ const { services, lota } = buildRuntimeServiceSurface({
246
+ managedRuntime,
247
+ db,
248
+ redisManager,
249
+ sharedSubscriber,
250
+ threadTurnService,
556
251
  socialChatHistoryService,
557
- get executionPlanService() {
558
- return resolveAwaitableService(ExecutionPlanServiceTag)
559
- },
560
- get planDeadlineService() {
561
- return resolveAwaitableService(PlanDeadlineServiceTag)
562
- },
563
- get planExecutorService() {
564
- return resolveAwaitableService(PlanExecutorServiceTag)
565
- },
566
- get planRunService() {
567
- return resolveAwaitableService(PlanRunServiceTag)
568
- },
569
- get planTemplateService() {
570
- return resolveAwaitableService(PlanTemplateServiceTag)
571
- },
572
- get planCoordinationService() {
573
- return resolveAwaitableService(PlanCoordinationServiceTag)
574
- },
575
- get planSchedulerService() {
576
- return resolveAwaitableService(PlanSchedulerServiceTag)
577
- },
578
- get planAgentHeartbeatService() {
579
- return resolveAwaitableService(PlanAgentHeartbeatServiceTag)
580
- },
581
- get planAgentQueryService() {
582
- return resolveAwaitableService(PlanAgentQueryServiceTag)
583
- },
584
- get planCycleService() {
585
- return resolveAwaitableService(PlanCycleServiceTag)
586
- },
587
- get threadMessageService() {
588
- return resolveAwaitableService(ThreadMessageServiceTag)
589
- },
590
- get threadService() {
591
- return resolveAwaitableService(ThreadServiceTag) as AwaitableThreadService
592
- },
593
- get threadTitleService() {
594
- return resolveAwaitableService(ThreadTitleServiceTag)
595
- },
596
- createThreadApprovalContinuationStream: (...args) =>
597
- runPromise(threadTurnService.createThreadApprovalContinuationStream(...args)),
598
- createThreadNativeToolApprovalStream: (...args) =>
599
- runPromise(threadTurnService.createThreadNativeToolApprovalStream(...args)),
600
- createThreadTurnStream: (...args) => runPromise(threadTurnService.createThreadTurnStream(...args)),
601
- isApprovalContinuationRequest: isApprovalContinuationRequestFn,
602
- runThreadTurnInBackground: (...args) => runPromise(threadTurnService.runThreadTurnInBackground(...args)),
603
- triggerPlanNodeTurn: (...args) => runPromise(threadTurnService.triggerPlanNodeTurn(...args)),
604
- }
605
-
606
- const lota: LotaRuntime['lota'] = {
607
- organizations: {
608
- create: (...args) => resolveAwaitableService(OrganizationServiceTag).createOrganization(...args),
609
- upsert: (...args) => resolveAwaitableService(OrganizationServiceTag).upsertOrganization(...args),
610
- get: (...args) => resolveAwaitableService(OrganizationServiceTag).getOrganization(...args),
611
- list: (...args) => resolveAwaitableService(OrganizationServiceTag).listOrganizations(...args),
612
- update: (...args) => resolveAwaitableService(OrganizationServiceTag).updateOrganization(...args),
613
- delete: (...args) => resolveAwaitableService(OrganizationServiceTag).deleteOrganization(...args),
614
- },
615
- users: {
616
- upsert: (...args) => resolveAwaitableService(UserServiceTag).upsertUser(...args),
617
- get: (...args) => resolveAwaitableService(UserServiceTag).getUser(...args),
618
- list: (...args) => resolveAwaitableService(UserServiceTag).listUsers(...args),
619
- update: (...args) => resolveAwaitableService(UserServiceTag).updateUser(...args),
620
- delete: (...args) => resolveAwaitableService(UserServiceTag).deleteUser(...args),
621
- },
622
- memberships: {
623
- add: (...args) => resolveAwaitableService(OrganizationMemberServiceTag).addMembership(...args),
624
- listForOrganization: (...args) =>
625
- resolveAwaitableService(OrganizationMemberServiceTag).listMembershipsForOrganization(...args),
626
- listForUser: (...args) =>
627
- resolveAwaitableService(OrganizationMemberServiceTag).listMembershipsForUser(...args),
628
- remove: (...args) => resolveAwaitableService(OrganizationMemberServiceTag).removeMembership(...args),
629
- isMember: (...args) => resolveAwaitableService(OrganizationMemberServiceTag).isMember(...args),
630
- },
631
- threads: {
632
- create: (...args) => resolveAwaitableService(ThreadServiceTag).createThread(...args),
633
- list: (...args) => resolveAwaitableService(ThreadServiceTag).listThreads(...args),
634
- get: (...args) => resolveAwaitableService(ThreadServiceTag).getThread(...args),
635
- update: (...args) => resolveAwaitableService(ThreadServiceTag).updateTitle(...args),
636
- archive: (threadId, status = 'archived') =>
637
- resolveAwaitableService(ThreadServiceTag).updateStatus(threadId, status),
638
- unarchive: (threadId, status = 'active') =>
639
- resolveAwaitableService(ThreadServiceTag).updateStatus(threadId, status),
640
- delete: (...args) => resolveAwaitableService(ThreadServiceTag).deleteThread(...args),
641
- stop: (...args) => resolveAwaitableService(ThreadServiceTag).stopActiveRun(...args),
642
- listMessages: (...args) => resolveAwaitableService(ThreadMessageServiceTag).listMessageHistoryPage(...args),
643
- getMessage: ({ threadId, messageId }) =>
644
- runPromise(
645
- Effect.gen(function* () {
646
- const messages = yield* resolve(ThreadMessageServiceTag).listMessages(
647
- ensureRecordId(threadId, TABLES.THREAD),
648
- )
649
- const message = messages.find((candidate: ChatMessage) => candidate.id === messageId)
650
- if (!message) {
651
- return yield* new NotFoundError({
652
- resource: 'Thread message',
653
- id: messageId,
654
- message: `Thread message not found: ${messageId}`,
655
- })
656
- }
657
- return message
658
- }),
659
- ),
660
- sendMessage: ({ threadId, organizationId, userId, userName, messages }) =>
661
- runPromise(
662
- Effect.gen(function* () {
663
- const threadRef = ensureRecordId(threadId, TABLES.THREAD)
664
- const thread = yield* resolve(ThreadServiceTag).getThread(threadRef)
665
- const routed = routeThreadChatMessages(messages)
666
- if (routed.kind !== 'turn') {
667
- return yield* new BadRequestError({
668
- message: routed.kind === 'invalid' ? routed.message : 'Expected a user turn payload.',
669
- })
670
- }
671
-
672
- return yield* threadTurnService.createThreadTurnStream({
673
- thread,
674
- threadRef,
675
- orgRef: ensureRecordId(organizationId, TABLES.ORGANIZATION),
676
- userRef: ensureRecordId(userId, TABLES.USER),
677
- userName,
678
- inputMessage: routed.inputMessage,
679
- })
680
- }),
681
- ),
682
- continueApproval: ({ threadId, organizationId, userId, userName, messages }) =>
683
- runPromise(
684
- Effect.gen(function* () {
685
- const threadRef = ensureRecordId(threadId, TABLES.THREAD)
686
- const thread = yield* resolve(ThreadServiceTag).getThread(threadRef)
687
- const routed = routeThreadChatMessages(messages)
688
- if (routed.kind !== 'approval-continuation') {
689
- return yield* new BadRequestError({
690
- message:
691
- routed.kind === 'invalid' ? routed.message : 'Expected approval continuation messages payload.',
692
- })
693
- }
694
-
695
- return yield* threadTurnService.createThreadApprovalContinuationStream({
696
- thread,
697
- threadRef,
698
- orgRef: ensureRecordId(organizationId, TABLES.ORGANIZATION),
699
- userRef: ensureRecordId(userId, TABLES.USER),
700
- userName,
701
- approvalMessages: routed.approvalMessages,
702
- })
703
- }),
704
- ),
705
- uploadAttachment: (...args) => resolveAwaitableService(AttachmentServiceTag).uploadThreadAttachment(...args),
706
- },
707
- }
252
+ })
708
253
 
709
- let disconnectPromise: Promise<void> | null = null
254
+ const disconnect = createRuntimeDisconnect({
255
+ managedRuntime,
256
+ runPromiseWithCurrentContext,
257
+ socialChatShutdown: () => socialChat.shutdown(),
258
+ disconnectPluginDatabases,
259
+ })
710
260
 
711
261
  const lotaRuntime: LotaRuntime = {
712
- runPromise: (effect, options) => managedRuntime.runPromise(effect, options),
713
- runSync: (effect) => managedRuntime.runSync(effect),
262
+ runPromise: <A, E, R>(effect: Effect.Effect<A, E, R>, options?: { readonly signal?: AbortSignal }) =>
263
+ managedRuntime.runPromise(effect as unknown as Effect.Effect<A, E, never>, options),
264
+ runSync: <A, E, R>(effect: Effect.Effect<A, E, R>) =>
265
+ managedRuntime.runSync(effect as unknown as Effect.Effect<A, E, never>),
266
+ runFork: <A, E, R>(effect: Effect.Effect<A, E, R>) =>
267
+ managedRuntime.runFork(effect as unknown as Effect.Effect<A, E, never>),
714
268
  services,
715
269
  lota,
716
270
  redis: {
@@ -718,7 +272,7 @@ export function createLotaRuntime(config: LotaRuntimeConfig): Promise<LotaRuntim
718
272
  subscriber: sharedSubscriber.subscriber,
719
273
  getConnection: () => redisManager.getConnection(),
720
274
  getConnectionForBullMQ: () => redisManager.getConnectionForBullMQ(),
721
- closeConnection: () => runPromise(effectTryPromise(() => redisManager.closeConnection())),
275
+ closeConnection: () => managedRuntime.runPromise(effectTryPromise(() => redisManager.closeConnection())),
722
276
  },
723
277
  workers,
724
278
  socialChat,
@@ -727,9 +281,9 @@ export function createLotaRuntime(config: LotaRuntimeConfig): Promise<LotaRuntim
727
281
  config: runtimeConfig,
728
282
  plugins: pluginRuntime,
729
283
  systemExecutors,
730
- connectPluginDatabases: () => runPromise(effectTryPromise(() => connectPluginDatabases())),
284
+ connectPluginDatabases,
731
285
  connect: () =>
732
- runPromise(
286
+ managedRuntime.runPromise(
733
287
  Effect.gen(function* () {
734
288
  yield* db.connect()
735
289
  const bunFiles = schemaFiles.map((schemaFile) =>
@@ -740,36 +294,14 @@ export function createLotaRuntime(config: LotaRuntimeConfig): Promise<LotaRuntim
740
294
  yield* publishDatabaseBootstrapEffect({ databaseService: db, schemaFingerprint })
741
295
  }),
742
296
  ),
743
- disconnect: () => {
744
- if (disconnectPromise) {
745
- return disconnectPromise
746
- }
747
-
748
- disconnectPromise = Effect.runPromise(
749
- Effect.gen(function* () {
750
- yield* Effect.ignore(effectTryPromise(() => socialChat.shutdown()))
751
- yield* Effect.ignore(effectTryPromise(() => disconnectPluginDatabases()))
752
- yield* effectTryPromise(() => managedRuntime.dispose())
753
- }).pipe(
754
- Effect.ensuring(
755
- Effect.sync(() => {
756
- clearLotaSdkRuntime()
757
- if (runtimeToken) releaseRuntimeToken(runtimeToken)
758
- }),
759
- ),
760
- ),
761
- )
762
- return disconnectPromise
763
- },
297
+ disconnect,
764
298
  }
765
299
  return lotaRuntime
766
300
  }),
767
301
  ).catch((error) => {
768
302
  if (effectRuntime) {
769
- clearLotaSdkRuntime()
770
303
  void effectRuntime.dispose().catch(() => undefined)
771
304
  }
772
- if (runtimeToken) releaseRuntimeToken(runtimeToken)
773
305
  throw error
774
306
  })
775
307
  }
@@ -790,60 +322,3 @@ function getBuiltInSchemaFiles(): URL[] {
790
322
  new URL('../infrastructure/schema/10_autonomous_job.surql', import.meta.url),
791
323
  ]
792
324
  }
793
-
794
- function getPluginLifecycleServices(plugin: LotaPlugin): PluginLifecycleServices {
795
- return plugin.services as PluginLifecycleServices
796
- }
797
-
798
- function createPluginDatabaseConnector(
799
- pluginRuntime: Record<string, LotaPlugin>,
800
- connectedPluginDatabases: Set<string>,
801
- ): () => Promise<void> {
802
- return () =>
803
- Effect.runPromise(
804
- Effect.gen(function* () {
805
- for (const [pluginName, plugin] of Object.entries(pluginRuntime)) {
806
- if (connectedPluginDatabases.has(pluginName)) {
807
- continue
808
- }
809
-
810
- const services = getPluginLifecycleServices(plugin)
811
- const connectDatabase = Reflect.get(services, 'connectDatabase')
812
- if (typeof connectDatabase !== 'function') {
813
- continue
814
- }
815
-
816
- const connectDatabaseFn = connectDatabase as (this: typeof services) => Promise<void>
817
- yield* effectTryPromise(() => connectDatabaseFn.call(services))
818
- connectedPluginDatabases.add(pluginName)
819
- }
820
- }),
821
- )
822
- }
823
-
824
- function createPluginDatabaseDisconnector(
825
- pluginRuntime: Record<string, LotaPlugin>,
826
- connectedPluginDatabases: Set<string>,
827
- ): () => Promise<void> {
828
- return () =>
829
- Effect.runPromise(
830
- Effect.gen(function* () {
831
- for (const [pluginName, plugin] of Object.entries(pluginRuntime)) {
832
- if (!connectedPluginDatabases.has(pluginName)) {
833
- continue
834
- }
835
-
836
- const services = getPluginLifecycleServices(plugin)
837
- const disconnectDatabase = Reflect.get(services, 'disconnectDatabase')
838
- if (typeof disconnectDatabase !== 'function') {
839
- connectedPluginDatabases.delete(pluginName)
840
- continue
841
- }
842
-
843
- const disconnectDatabaseFn = disconnectDatabase as (this: typeof services) => Promise<void>
844
- yield* effectTryPromise(() => disconnectDatabaseFn.call(services))
845
- connectedPluginDatabases.delete(pluginName)
846
- }
847
- }),
848
- )
849
- }