@lota-sdk/core 0.4.13 → 0.4.14

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 (138) 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/create-runtime.ts +259 -200
  8. package/src/db/cursor-pagination.ts +2 -9
  9. package/src/db/memory-store.ts +194 -175
  10. package/src/db/memory.ts +125 -71
  11. package/src/db/schema-fingerprint.ts +5 -4
  12. package/src/db/service-normalization.ts +4 -3
  13. package/src/db/service.ts +3 -2
  14. package/src/db/startup.ts +15 -16
  15. package/src/effect/errors.ts +161 -21
  16. package/src/effect/index.ts +0 -1
  17. package/src/embeddings/provider.ts +15 -7
  18. package/src/queues/autonomous-job.queue.ts +10 -22
  19. package/src/queues/delayed-node-promotion.queue.ts +8 -14
  20. package/src/queues/document-processor.queue.ts +13 -4
  21. package/src/queues/memory-consolidation.queue.ts +26 -14
  22. package/src/queues/plan-agent-heartbeat.queue.ts +10 -9
  23. package/src/queues/plan-scheduler.queue.ts +37 -15
  24. package/src/queues/queue-factory.ts +59 -35
  25. package/src/queues/standalone-worker.ts +3 -2
  26. package/src/redis/connection.ts +10 -3
  27. package/src/redis/org-memory-lock.ts +1 -1
  28. package/src/redis/redis-lease-lock.ts +5 -5
  29. package/src/redis/stream-context.ts +1 -1
  30. package/src/runtime/chat-message.ts +64 -1
  31. package/src/runtime/chat-run-orchestration.ts +33 -20
  32. package/src/runtime/context-compaction/context-compaction-runtime.ts +14 -7
  33. package/src/runtime/context-compaction/context-compaction.ts +78 -66
  34. package/src/runtime/domain-layer.ts +13 -7
  35. package/src/runtime/execution-plan.ts +7 -3
  36. package/src/runtime/memory/memory-block.ts +3 -9
  37. package/src/runtime/memory/memory-scope.ts +3 -1
  38. package/src/runtime/plugin-resolution.ts +2 -1
  39. package/src/runtime/post-turn-side-effects.ts +6 -5
  40. package/src/runtime/retrieval-adapters.ts +8 -20
  41. package/src/runtime/runtime-config.ts +3 -9
  42. package/src/runtime/runtime-extensions.ts +2 -4
  43. package/src/runtime/runtime-lifecycle.ts +56 -16
  44. package/src/runtime/runtime-services.ts +180 -102
  45. package/src/runtime/runtime-worker-registry.ts +3 -1
  46. package/src/runtime/social-chat/social-chat-agent-runner.ts +1 -1
  47. package/src/runtime/social-chat/social-chat-history.ts +21 -18
  48. package/src/runtime/social-chat/social-chat.ts +356 -223
  49. package/src/runtime/specialist-runner.ts +3 -1
  50. package/src/runtime/team-consultation/team-consultation-orchestrator.ts +3 -2
  51. package/src/runtime/thread-turn-context.ts +142 -102
  52. package/src/runtime/turn-lifecycle.ts +15 -46
  53. package/src/services/agent-activity.service.ts +1 -1
  54. package/src/services/agent-executor.service.ts +107 -77
  55. package/src/services/autonomous-job.service.ts +354 -293
  56. package/src/services/background-work.service.ts +3 -3
  57. package/src/services/context-compaction.service.ts +7 -2
  58. package/src/services/document-chunk.service.ts +50 -32
  59. package/src/services/execution-plan/execution-plan-schedule.ts +5 -3
  60. package/src/services/execution-plan/execution-plan.service.ts +162 -179
  61. package/src/services/feedback-loop.service.ts +5 -4
  62. package/src/services/graph-full-routing.ts +37 -36
  63. package/src/services/institutional-memory.service.ts +28 -30
  64. package/src/services/learned-skill.service.ts +107 -72
  65. package/src/services/memory/memory-errors.ts +4 -23
  66. package/src/services/memory/memory-org-memory.ts +10 -5
  67. package/src/services/memory/memory-rerank.ts +18 -6
  68. package/src/services/memory/memory.service.ts +170 -111
  69. package/src/services/memory/rerank.service.ts +29 -20
  70. package/src/services/organization-member.service.ts +1 -1
  71. package/src/services/organization.service.ts +69 -75
  72. package/src/services/ownership-dispatcher.service.ts +40 -39
  73. package/src/services/plan/plan-agent-heartbeat.service.ts +26 -23
  74. package/src/services/plan/plan-agent-query.service.ts +39 -31
  75. package/src/services/plan/plan-completion-side-effects.ts +13 -17
  76. package/src/services/plan/plan-coordination.service.ts +2 -1
  77. package/src/services/plan/plan-cycle.service.ts +6 -5
  78. package/src/services/plan/plan-deadline.service.ts +57 -54
  79. package/src/services/plan/plan-event-delivery.service.ts +5 -4
  80. package/src/services/plan/plan-executor-graph.ts +18 -15
  81. package/src/services/plan/plan-executor.service.ts +235 -262
  82. package/src/services/plan/plan-run.service.ts +169 -93
  83. package/src/services/plan/plan-scheduler.service.ts +192 -202
  84. package/src/services/plan/plan-template.service.ts +1 -1
  85. package/src/services/plan/plan-transaction-events.ts +1 -1
  86. package/src/services/plan/plan-workspace.service.ts +23 -14
  87. package/src/services/plugin-executor.service.ts +5 -9
  88. package/src/services/queue-job.service.ts +117 -59
  89. package/src/services/recent-activity-title.service.ts +13 -12
  90. package/src/services/recent-activity.service.ts +6 -1
  91. package/src/services/social-chat-history.service.ts +29 -25
  92. package/src/services/system-executor.service.ts +5 -9
  93. package/src/services/thread/thread-active-run.ts +2 -2
  94. package/src/services/thread/thread-listing.ts +61 -57
  95. package/src/services/thread/thread-memory-block.ts +73 -48
  96. package/src/services/thread/thread-message.service.ts +76 -65
  97. package/src/services/thread/thread-record-store.ts +8 -8
  98. package/src/services/thread/thread-title.service.ts +10 -4
  99. package/src/services/thread/thread-turn-execution.ts +43 -45
  100. package/src/services/thread/thread-turn-preparation.service.ts +257 -135
  101. package/src/services/thread/thread-turn-streaming.ts +82 -85
  102. package/src/services/thread/thread-turn.ts +8 -8
  103. package/src/services/thread/thread.service.ts +135 -100
  104. package/src/services/user.service.ts +45 -48
  105. package/src/storage/attachment-parser.ts +6 -2
  106. package/src/storage/attachment-storage.service.ts +5 -6
  107. package/src/storage/generated-document-storage.service.ts +1 -1
  108. package/src/system-agents/context-compaction.agent.ts +10 -9
  109. package/src/system-agents/delegated-agent-factory.ts +30 -6
  110. package/src/system-agents/memory-reranker.agent.ts +10 -9
  111. package/src/system-agents/memory.agent.ts +10 -9
  112. package/src/system-agents/recent-activity-title-refiner.agent.ts +13 -15
  113. package/src/system-agents/regular-chat-memory-digest.agent.ts +13 -12
  114. package/src/system-agents/skill-extractor.agent.ts +13 -12
  115. package/src/system-agents/skill-manager.agent.ts +13 -12
  116. package/src/system-agents/thread-router.agent.ts +10 -5
  117. package/src/system-agents/title-generator.agent.ts +13 -12
  118. package/src/tools/fetch-webpage.tool.ts +13 -13
  119. package/src/tools/memory-block.tool.ts +3 -1
  120. package/src/tools/plan-approval.tool.ts +4 -2
  121. package/src/tools/read-file-parts.tool.ts +10 -4
  122. package/src/tools/remember-memory.tool.ts +3 -1
  123. package/src/tools/research-topic.tool.ts +9 -5
  124. package/src/tools/search-web.tool.ts +16 -16
  125. package/src/tools/search.tool.ts +20 -5
  126. package/src/tools/team-think.tool.ts +61 -38
  127. package/src/utils/async.ts +5 -5
  128. package/src/utils/errors.ts +19 -18
  129. package/src/utils/sse-keepalive.ts +28 -25
  130. package/src/workers/bootstrap.ts +75 -11
  131. package/src/workers/memory-consolidation.worker.ts +82 -91
  132. package/src/workers/organization-learning.worker.ts +14 -4
  133. package/src/workers/regular-chat-memory-digest.runner.ts +105 -67
  134. package/src/workers/skill-extraction.runner.ts +97 -61
  135. package/src/workers/utils/repo-structure-extractor.ts +13 -8
  136. package/src/workers/utils/thread-message-query.ts +24 -24
  137. package/src/workers/worker-utils.ts +23 -4
  138. package/src/effect/helpers.ts +0 -123
@@ -4,65 +4,186 @@ const ValidationIssueSchema = Schema.Struct({ path: Schema.String, message: Sche
4
4
 
5
5
  export type ValidationIssue = typeof ValidationIssueSchema.Type
6
6
 
7
- export class DatabaseError extends Schema.TaggedErrorClass<DatabaseError>()('DatabaseError', {
7
+ /**
8
+ * Single source of truth for every Effect tagged-error `_tag` value in the
9
+ * SDK. Referenced by:
10
+ * - `Schema.TaggedErrorClass<X>()(ERROR_TAGS.X, ...)` at definition time,
11
+ * - `Match.tag(ERROR_TAGS.X, ...)` / `Effect.catchTag(ERROR_TAGS.X, ...)` /
12
+ * `Effect.catchTags({ [ERROR_TAGS.X]: ... })` at consumer sites,
13
+ * - `isBaseServicePersistenceError` / any `_tag === ...` compare.
14
+ *
15
+ * Using these constants instead of literal strings prevents typos breaking
16
+ * catchTag pattern-matching and ensures tag renames stay in lockstep with
17
+ * consumers.
18
+ */
19
+ export const ERROR_TAGS = {
20
+ ActiveThreadRunConflictError: '@lota-sdk/core/ActiveThreadRunConflictError',
21
+ AgentExecutorError: '@lota-sdk/core/AgentExecutorError',
22
+ AiGenerationError: '@lota-sdk/core/AiGenerationError',
23
+ AttachmentParserError: '@lota-sdk/core/AttachmentParserError',
24
+ AttachmentStorageError: '@lota-sdk/core/AttachmentStorageError',
25
+ BadRequestError: '@lota-sdk/core/BadRequestError',
26
+ BaseServicePersistenceError: '@lota-sdk/core/BaseServicePersistenceError',
27
+ CompactionError: '@lota-sdk/core/CompactionError',
28
+ CompactionParseError: '@lota-sdk/core/CompactionParseError',
29
+ ConfigurationError: '@lota-sdk/core/ConfigurationError',
30
+ ConflictError: '@lota-sdk/core/ConflictError',
31
+ ContextCompactionRuntimeError: '@lota-sdk/core/ContextCompactionRuntimeError',
32
+ CursorPaginationError: '@lota-sdk/core/CursorPaginationError',
33
+ DatabaseError: '@lota-sdk/core/DatabaseError',
34
+ DelegatedAgentError: '@lota-sdk/core/DelegatedAgentError',
35
+ EmbeddingCacheError: '@lota-sdk/core/EmbeddingCacheError',
36
+ EmbeddingProviderError: '@lota-sdk/core/EmbeddingProviderError',
37
+ ExecutionPlanCacheError: '@lota-sdk/core/ExecutionPlanCacheError',
38
+ FeedbackLoopServiceError: '@lota-sdk/core/FeedbackLoopServiceError',
39
+ ForbiddenError: '@lota-sdk/core/ForbiddenError',
40
+ GeneratedDocumentStorageError: '@lota-sdk/core/GeneratedDocumentStorageError',
41
+ InvalidAgentNameError: '@lota-sdk/core/InvalidAgentNameError',
42
+ LearnedSkillNotFoundError: '@lota-sdk/core/LearnedSkillNotFoundError',
43
+ LearnedSkillServiceError: '@lota-sdk/core/LearnedSkillServiceError',
44
+ LockAcquisitionError: '@lota-sdk/core/LockAcquisitionError',
45
+ LockLostError: '@lota-sdk/core/LockLostError',
46
+ MemoryBlockCompactError: '@lota-sdk/core/MemoryBlockCompactError',
47
+ MemoryConsolidationError: '@lota-sdk/core/MemoryConsolidationError',
48
+ MemoryDigestError: '@lota-sdk/core/MemoryDigestError',
49
+ MemoryRerankError: '@lota-sdk/core/MemoryRerankError',
50
+ MemoryScopeError: '@lota-sdk/core/MemoryScopeError',
51
+ MemoryServiceError: '@lota-sdk/core/MemoryServiceError',
52
+ MemoryStoreError: '@lota-sdk/core/MemoryStoreError',
53
+ NotFoundError: '@lota-sdk/core/NotFoundError',
54
+ OrgMemoryLockCallbackError: '@lota-sdk/core/OrgMemoryLockCallbackError',
55
+ OrganizationMemberServiceError: '@lota-sdk/core/OrganizationMemberServiceError',
56
+ OrganizationServiceError: '@lota-sdk/core/OrganizationServiceError',
57
+ PlanAgentHeartbeatError: '@lota-sdk/core/PlanAgentHeartbeatError',
58
+ PlanAgentQueryError: '@lota-sdk/core/PlanAgentQueryError',
59
+ PlanCoordinationError: '@lota-sdk/core/PlanCoordinationError',
60
+ PlanCycleNotFoundError: '@lota-sdk/core/PlanCycleNotFoundError',
61
+ PlanDeadlineError: '@lota-sdk/core/PlanDeadlineError',
62
+ PlanEventDeliveryError: '@lota-sdk/core/PlanEventDeliveryError',
63
+ PlanExecutorGraphError: '@lota-sdk/core/PlanExecutorGraphError',
64
+ PlanExecutorInternalError: '@lota-sdk/core/PlanExecutorInternalError',
65
+ PlanRunNotFoundError: '@lota-sdk/core/PlanRunNotFoundError',
66
+ PlanRunServiceError: '@lota-sdk/core/PlanRunServiceError',
67
+ PlanScheduleAttachError: '@lota-sdk/core/PlanScheduleAttachError',
68
+ PlanSchedulerError: '@lota-sdk/core/PlanSchedulerError',
69
+ PlanSchedulerQueueError: '@lota-sdk/core/PlanSchedulerQueueError',
70
+ PluginResolutionError: '@lota-sdk/core/PluginResolutionError',
71
+ PostTurnSideEffectsError: '@lota-sdk/core/PostTurnSideEffectsError',
72
+ QueueFactoryError: '@lota-sdk/core/QueueFactoryError',
73
+ QueueWorkerError: '@lota-sdk/core/QueueWorkerError',
74
+ ReadFilePartsError: '@lota-sdk/core/ReadFilePartsError',
75
+ RedisError: '@lota-sdk/core/RedisError',
76
+ RerankServiceError: '@lota-sdk/core/RerankServiceError',
77
+ RuntimeLifecycleError: '@lota-sdk/core/RuntimeLifecycleError',
78
+ SandboxedWorkerBootstrapError: '@lota-sdk/core/SandboxedWorkerBootstrapError',
79
+ SchemaFingerprintError: '@lota-sdk/core/SchemaFingerprintError',
80
+ ScopedRetrievalError: '@lota-sdk/core/ScopedRetrievalError',
81
+ SearchWebToolError: '@lota-sdk/core/SearchWebToolError',
82
+ ServiceError: '@lota-sdk/core/ServiceError',
83
+ SharedSubscriberCloseError: '@lota-sdk/core/SharedSubscriberCloseError',
84
+ SocialChatAgentRunnerError: '@lota-sdk/core/SocialChatAgentRunnerError',
85
+ SocialChatHistoryError: '@lota-sdk/core/SocialChatHistoryError',
86
+ SocialChatServiceError: '@lota-sdk/core/SocialChatServiceError',
87
+ SpecialistRunnerError: '@lota-sdk/core/SpecialistRunnerError',
88
+ StandaloneQueueWorkerError: '@lota-sdk/core/StandaloneQueueWorkerError',
89
+ SseKeepaliveError: '@lota-sdk/core/SseKeepaliveError',
90
+ SurrealDBError: '@lota-sdk/core/SurrealDBError',
91
+ TeamConsultationError: '@lota-sdk/core/TeamConsultationError',
92
+ TeamThinkAgentFactoryNotConfiguredError: '@lota-sdk/core/TeamThinkAgentFactoryNotConfiguredError',
93
+ TeamThinkRuntimeError: '@lota-sdk/core/TeamThinkRuntimeError',
94
+ ThreadListingError: '@lota-sdk/core/ThreadListingError',
95
+ ThreadMemoryBlockError: '@lota-sdk/core/ThreadMemoryBlockError',
96
+ ThreadMessageQueryError: '@lota-sdk/core/ThreadMessageQueryError',
97
+ ThreadTitleError: '@lota-sdk/core/ThreadTitleError',
98
+ ThreadTurnContextError: '@lota-sdk/core/ThreadTurnContextError',
99
+ ThreadTurnError: '@lota-sdk/core/ThreadTurnError',
100
+ ThreadTurnPreparationError: '@lota-sdk/core/ThreadTurnPreparationError',
101
+ ThreadTurnServiceError: '@lota-sdk/core/ThreadTurnServiceError',
102
+ ThreadTurnStreamingError: '@lota-sdk/core/ThreadTurnStreamingError',
103
+ TimedOperationError: '@lota-sdk/core/TimedOperationError',
104
+ TimeoutError: '@lota-sdk/core/TimeoutError',
105
+ TurnLifecycleError: '@lota-sdk/core/TurnLifecycleError',
106
+ UserServiceError: '@lota-sdk/core/UserServiceError',
107
+ ValidationError: '@lota-sdk/core/ValidationError',
108
+ WaitForCompactionError: '@lota-sdk/core/WaitForCompactionError',
109
+ } as const
110
+
111
+ type ErrorTag = (typeof ERROR_TAGS)[keyof typeof ERROR_TAGS]
112
+
113
+ export class DatabaseError extends Schema.TaggedErrorClass<DatabaseError>()(ERROR_TAGS.DatabaseError, {
8
114
  message: Schema.String,
9
115
  query: Schema.optional(Schema.String),
10
116
  cause: Schema.optional(Schema.Defect),
11
117
  }) {}
12
118
 
13
- export class ServiceError extends Schema.TaggedErrorClass<ServiceError>()('ServiceError', {
119
+ export class ServiceError extends Schema.TaggedErrorClass<ServiceError>()(ERROR_TAGS.ServiceError, {
14
120
  message: Schema.String,
15
121
  cause: Schema.optional(Schema.Defect),
16
122
  }) {}
17
123
 
18
124
  export class BaseServicePersistenceError extends Schema.TaggedErrorClass<BaseServicePersistenceError>()(
19
- 'BaseServicePersistenceError',
125
+ ERROR_TAGS.BaseServicePersistenceError,
20
126
  { message: Schema.String, cause: Schema.Defect },
21
127
  ) {}
22
128
 
23
- export class RedisError extends Schema.TaggedErrorClass<RedisError>()('RedisError', {
129
+ export class RedisError extends Schema.TaggedErrorClass<RedisError>()(ERROR_TAGS.RedisError, {
24
130
  message: Schema.String,
25
131
  cause: Schema.optional(Schema.Defect),
26
132
  }) {}
27
133
 
28
- export class TimeoutError extends Schema.TaggedErrorClass<TimeoutError>()('TimeoutError', {
134
+ export class RuntimeLifecycleError extends Schema.TaggedErrorClass<RuntimeLifecycleError>()(
135
+ ERROR_TAGS.RuntimeLifecycleError,
136
+ {
137
+ operation: Schema.Literals([
138
+ 'connect-plugin-database',
139
+ 'disconnect-plugin-database',
140
+ 'shutdown-social-chat',
141
+ 'disconnect-plugin-databases',
142
+ 'dispose-managed-runtime',
143
+ ]),
144
+ message: Schema.String,
145
+ cause: Schema.optional(Schema.Defect),
146
+ },
147
+ ) {}
148
+
149
+ export class TimeoutError extends Schema.TaggedErrorClass<TimeoutError>()(ERROR_TAGS.TimeoutError, {
29
150
  operation: Schema.String,
30
151
  ms: Schema.Number,
31
152
  }) {}
32
153
 
33
- export class LockAcquisitionError extends Schema.TaggedErrorClass<LockAcquisitionError>()('LockAcquisitionError', {
34
- lockKey: Schema.String,
35
- maxWaitMs: Schema.Number,
36
- }) {}
154
+ export class LockAcquisitionError extends Schema.TaggedErrorClass<LockAcquisitionError>()(
155
+ ERROR_TAGS.LockAcquisitionError,
156
+ { lockKey: Schema.String, maxWaitMs: Schema.Number },
157
+ ) {}
37
158
 
38
- export class LockLostError extends Schema.TaggedErrorClass<LockLostError>()('LockLostError', {
159
+ export class LockLostError extends Schema.TaggedErrorClass<LockLostError>()(ERROR_TAGS.LockLostError, {
39
160
  lockKey: Schema.String,
40
161
  }) {}
41
162
 
42
- export class NotFoundError extends Schema.TaggedErrorClass<NotFoundError>()('NotFoundError', {
163
+ export class NotFoundError extends Schema.TaggedErrorClass<NotFoundError>()(ERROR_TAGS.NotFoundError, {
43
164
  resource: Schema.String,
44
165
  id: Schema.optional(Schema.String),
45
166
  message: Schema.String,
46
167
  }) {}
47
168
 
48
- export class BadRequestError extends Schema.TaggedErrorClass<BadRequestError>()('BadRequestError', {
169
+ export class BadRequestError extends Schema.TaggedErrorClass<BadRequestError>()(ERROR_TAGS.BadRequestError, {
49
170
  message: Schema.String,
50
171
  }) {}
51
172
 
52
- export class ConflictError extends Schema.TaggedErrorClass<ConflictError>()('ConflictError', {
173
+ export class ConflictError extends Schema.TaggedErrorClass<ConflictError>()(ERROR_TAGS.ConflictError, {
53
174
  message: Schema.String,
54
175
  }) {}
55
176
 
56
- export class ForbiddenError extends Schema.TaggedErrorClass<ForbiddenError>()('ForbiddenError', {
177
+ export class ForbiddenError extends Schema.TaggedErrorClass<ForbiddenError>()(ERROR_TAGS.ForbiddenError, {
57
178
  message: Schema.String,
58
179
  }) {}
59
180
 
60
- export class ValidationError extends Schema.TaggedErrorClass<ValidationError>()('ValidationError', {
181
+ export class ValidationError extends Schema.TaggedErrorClass<ValidationError>()(ERROR_TAGS.ValidationError, {
61
182
  message: Schema.String,
62
183
  issues: Schema.optional(Schema.Array(ValidationIssueSchema)),
63
184
  }) {}
64
185
 
65
- export class AiGenerationError extends Schema.TaggedErrorClass<AiGenerationError>()('AiGenerationError', {
186
+ export class AiGenerationError extends Schema.TaggedErrorClass<AiGenerationError>()(ERROR_TAGS.AiGenerationError, {
66
187
  message: Schema.String,
67
188
  source: Schema.String,
68
189
  status: Schema.optional(Schema.Number),
@@ -73,17 +194,17 @@ export class AiGenerationError extends Schema.TaggedErrorClass<AiGenerationError
73
194
  url: Schema.optional(Schema.String),
74
195
  }) {}
75
196
 
76
- export class ThreadTurnError extends Schema.TaggedErrorClass<ThreadTurnError>()('ThreadTurnError', {
197
+ export class ThreadTurnError extends Schema.TaggedErrorClass<ThreadTurnError>()(ERROR_TAGS.ThreadTurnError, {
77
198
  message: Schema.String,
78
199
  reason: Schema.Literals(['bad-request', 'conflict']),
79
200
  }) {}
80
201
 
81
202
  export class ActiveThreadRunConflictError extends Schema.TaggedErrorClass<ActiveThreadRunConflictError>()(
82
- 'ActiveThreadRunConflictError',
203
+ ERROR_TAGS.ActiveThreadRunConflictError,
83
204
  { threadId: Schema.String, activeRunId: Schema.String, message: Schema.String },
84
205
  ) {}
85
206
 
86
- export class ConfigurationError extends Schema.TaggedErrorClass<ConfigurationError>()('ConfigurationError', {
207
+ export class ConfigurationError extends Schema.TaggedErrorClass<ConfigurationError>()(ERROR_TAGS.ConfigurationError, {
87
208
  message: Schema.String,
88
209
  key: Schema.optional(Schema.String),
89
210
  }) {}
@@ -101,6 +222,7 @@ const EFFECT_ERROR_CLASSES = [
101
222
  LockLostError,
102
223
  NotFoundError,
103
224
  RedisError,
225
+ RuntimeLifecycleError,
104
226
  ServiceError,
105
227
  ThreadTurnError,
106
228
  TimeoutError,
@@ -109,7 +231,25 @@ const EFFECT_ERROR_CLASSES = [
109
231
 
110
232
  export type EffectError = InstanceType<(typeof EFFECT_ERROR_CLASSES)[number]>
111
233
 
112
- const EFFECT_ERROR_TAGS = new Set(EFFECT_ERROR_CLASSES.map((cls) => cls.name))
234
+ const EFFECT_ERROR_TAGS = new Set<ErrorTag>([
235
+ ERROR_TAGS.ActiveThreadRunConflictError,
236
+ ERROR_TAGS.AiGenerationError,
237
+ ERROR_TAGS.BadRequestError,
238
+ ERROR_TAGS.BaseServicePersistenceError,
239
+ ERROR_TAGS.ConfigurationError,
240
+ ERROR_TAGS.ConflictError,
241
+ ERROR_TAGS.DatabaseError,
242
+ ERROR_TAGS.ForbiddenError,
243
+ ERROR_TAGS.LockAcquisitionError,
244
+ ERROR_TAGS.LockLostError,
245
+ ERROR_TAGS.NotFoundError,
246
+ ERROR_TAGS.RedisError,
247
+ ERROR_TAGS.RuntimeLifecycleError,
248
+ ERROR_TAGS.ServiceError,
249
+ ERROR_TAGS.ThreadTurnError,
250
+ ERROR_TAGS.TimeoutError,
251
+ ERROR_TAGS.ValidationError,
252
+ ])
113
253
 
114
254
  export function isEffectError(error: unknown): error is EffectError {
115
255
  if (!error || typeof error !== 'object') {
@@ -117,5 +257,5 @@ export function isEffectError(error: unknown): error is EffectError {
117
257
  }
118
258
 
119
259
  const tag = (error as { _tag?: unknown })._tag
120
- return typeof tag === 'string' && EFFECT_ERROR_TAGS.has(tag)
260
+ return typeof tag === 'string' && EFFECT_ERROR_TAGS.has(tag as ErrorTag)
121
261
  }
@@ -1,4 +1,3 @@
1
- export * from './helpers'
2
1
  export * from './layers'
3
2
  export * from './services'
4
3
  export * from './zod'
@@ -1,7 +1,7 @@
1
1
  import { embed, embedMany } from 'ai'
2
2
  import { Schema, Effect } from 'effect'
3
3
 
4
- import { ConfigurationError } from '../effect/errors'
4
+ import { ERROR_TAGS, ConfigurationError } from '../effect/errors'
5
5
  import { getDirectOpenRouterProvider, normalizeDirectOpenRouterModelId } from '../openrouter/direct-provider'
6
6
 
7
7
  const SUPPORTED_EMBEDDING_PREFIXES = ['openai/', 'openrouter/'] as const
@@ -17,6 +17,12 @@ type ProviderEmbeddingsOptions = {
17
17
  getCache?: () => SharedEmbeddingCache | null
18
18
  modelId: string
19
19
  openRouterApiKey?: string
20
+ /**
21
+ * `runPromise` is required: callers must yield `RuntimeBridgeTag` in their
22
+ * `Layer.effect` (or accept a `RuntimeBridge` dep) and pass its `runPromise`
23
+ * through, so this class never reaches for an ambient `Effect.runPromise`.
24
+ */
25
+ runPromise: <A, E>(effect: Effect.Effect<A, E>) => Promise<A>
20
26
  }
21
27
 
22
28
  function resolveEmbeddingModel(modelId: string, openRouterApiKey?: string) {
@@ -39,10 +45,10 @@ function normalizeEmbedding(embedding: readonly number[]): number[] {
39
45
  return embedding.map((value) => Number(value))
40
46
  }
41
47
 
42
- class EmbeddingProviderError extends Schema.TaggedErrorClass<EmbeddingProviderError>()('EmbeddingProviderError', {
43
- message: Schema.String,
44
- cause: Schema.Defect,
45
- }) {}
48
+ class EmbeddingProviderError extends Schema.TaggedErrorClass<EmbeddingProviderError>()(
49
+ ERROR_TAGS.EmbeddingProviderError,
50
+ { message: Schema.String, cause: Schema.Defect },
51
+ ) {}
46
52
 
47
53
  function tryEmbeddingPromise<A>(
48
54
  message: string,
@@ -64,6 +70,7 @@ export class ProviderEmbeddings {
64
70
  private readonly inflightEmbeddings = new Map<string, Promise<number[]>>()
65
71
 
66
72
  private readonly openRouterApiKey: string | undefined
73
+ private readonly runPromise: <A, E>(effect: Effect.Effect<A, E>) => Promise<A>
67
74
 
68
75
  constructor(options: ProviderEmbeddingsOptions) {
69
76
  this.embedFn = options.embedFn ?? embed
@@ -71,6 +78,7 @@ export class ProviderEmbeddings {
71
78
  this.getCache = options.getCache ?? (() => null)
72
79
  this.resolvedModelId = options.modelId
73
80
  this.openRouterApiKey = options.openRouterApiKey
81
+ this.runPromise = options.runPromise
74
82
  }
75
83
 
76
84
  private getModelId(): string {
@@ -99,7 +107,7 @@ export class ProviderEmbeddings {
99
107
  const pending = this.inflightEmbeddings.get(dedupKey)
100
108
  if (pending) return pending
101
109
 
102
- const promise = Effect.runPromise(this.executeEmbedQueryEffect(input))
110
+ const promise = this.runPromise(this.executeEmbedQueryEffect(input))
103
111
  this.inflightEmbeddings.set(dedupKey, promise)
104
112
  void promise.finally(() => this.inflightEmbeddings.delete(dedupKey))
105
113
 
@@ -144,7 +152,7 @@ export class ProviderEmbeddings {
144
152
  }
145
153
 
146
154
  const uniqueTexts = [...new Set(nonEmptyEntries.map((entry) => entry.value))]
147
- return Effect.runPromise(this.embedDocumentsEffect(normalized, uniqueTexts))
155
+ return this.runPromise(this.embedDocumentsEffect(normalized, uniqueTexts))
148
156
  }
149
157
 
150
158
  private embedDocumentsEffect(
@@ -6,6 +6,7 @@ import type IORedis from 'ioredis'
6
6
 
7
7
  import { serverLogger } from '../config/logger'
8
8
  import { DatabaseServiceTag, RedisServiceTag } from '../effect/services'
9
+ import type { makeAutonomousJobService } from '../services/autonomous-job.service'
9
10
  import { QueueJobServiceTag } from '../services/queue-job.service'
10
11
  import { buildAutonomousAtJobId } from '../utils/autonomous-job-ids'
11
12
  import type { QueueJobService, WorkerHandle } from '../workers/worker-utils'
@@ -13,17 +14,12 @@ import { DEFAULT_JOB_RETENTION } from '../workers/worker-utils'
13
14
  import { createQueueFactoryWithDeps, recordEnqueuedJobMetadata } from './queue-factory'
14
15
  import { runStandaloneQueueWorker } from './standalone-worker'
15
16
 
16
- // Minimal service shape used by the queue's worker processor. We declare it
17
- // structurally to avoid importing `AutonomousJobServiceTag` — that would form a
18
- // dependency cycle since `AutonomousJobServiceLive` now depends on
19
- // `LotaQueuesServiceTag` (defined in `queues.service.ts` which imports this
20
- // module).
21
- interface AutonomousJobWorkerServiceShape {
22
- executeQueuedRun(
23
- job: Job<AutonomousJobQueuePayload>,
24
- ): Effect.Effect<{ status: string; summary?: string }, unknown, unknown>
25
- recoverActiveJobs(): Effect.Effect<unknown, unknown, unknown>
26
- }
17
+ type AutonomousJobWorkerServiceMethods = Pick<
18
+ ReturnType<typeof makeAutonomousJobService>,
19
+ 'executeQueuedRun' | 'recoverActiveJobs'
20
+ >
21
+
22
+ type AutonomousJobWorkerServiceShape = AutonomousJobWorkerServiceMethods
27
23
 
28
24
  class AutonomousJobQueueError extends Schema.TaggedErrorClass<AutonomousJobQueueError>()(
29
25
  '@lota-sdk/core/AutonomousJobQueueError',
@@ -53,16 +49,7 @@ function processAutonomousJob(
53
49
  deps: AutonomousJobWorkerDeps,
54
50
  job: Job<AutonomousJobQueuePayload>,
55
51
  ): Promise<{ status: string; summary?: string }> {
56
- // `executeQueuedRun` is typed with a wide residual context to account for
57
- // the dynamic thread-turn import inside the service; the actual Effect
58
- // resolves every tag via the managed runtime that produced this service.
59
- return Effect.runPromise(
60
- deps.autonomousJobService.executeQueuedRun(job) as Effect.Effect<
61
- { status: string; summary?: string },
62
- never,
63
- never
64
- >,
65
- )
52
+ return Effect.runPromise(deps.autonomousJobService.executeQueuedRun(job))
66
53
  }
67
54
 
68
55
  function buildAutonomousSchedulerId(autonomousJobId: string): string {
@@ -193,7 +180,7 @@ export function makeAutonomousJobQueueRuntime(params: MakeAutonomousJobQueueRunt
193
180
  Effect.sync(() => {
194
181
  serverLogger.error`Autonomous job startup recovery failed: ${error}`
195
182
  }),
196
- ) as Effect.Effect<unknown, never, never>,
183
+ ),
197
184
  )
198
185
 
199
186
  return handle
@@ -209,6 +196,7 @@ export function makeAutonomousJobQueueRuntime(params: MakeAutonomousJobQueueRunt
209
196
  }
210
197
 
211
198
  runStandaloneQueueWorker((runtime) => {
199
+ // @effect-diagnostics-next-line asyncFunction:off -- BullMQ standalone worker bootstrap.
212
200
  void (async () => {
213
201
  const { AutonomousJobServiceTag } = await import('../services/autonomous-job.service')
214
202
  const resolve = <I, T>(tag: Context.Key<I, T>): T => runtime.runSync(Effect.service(tag))
@@ -4,21 +4,15 @@ import type { Context } from 'effect'
4
4
  import type IORedis from 'ioredis'
5
5
 
6
6
  import { DatabaseServiceTag, RedisServiceTag } from '../effect/services'
7
+ import type { makePlanExecutorService } from '../services/plan/plan-executor.service'
7
8
  import { QueueJobServiceTag } from '../services/queue-job.service'
8
9
  import type { QueueJobService, WorkerHandle } from '../workers/worker-utils'
9
10
  import { createQueueFactoryWithDeps } from './queue-factory'
10
11
  import { runStandaloneQueueWorker } from './standalone-worker'
11
12
 
12
- // Minimal service shape used by the worker processor. Declared structurally to
13
- // avoid importing the service tag — which would form a dependency cycle since
14
- // PlanExecutorServiceLive depends on LotaQueuesServiceTag.
15
- interface DelayedNodePromotionPlanExecutorShape {
16
- promoteDelayedNode(params: {
17
- runId: string
18
- nodeId: string
19
- emittedBy: string
20
- }): Effect.Effect<unknown, unknown, unknown>
21
- }
13
+ type DelayedNodePromotionPlanExecutorMethods = Pick<ReturnType<typeof makePlanExecutorService>, 'promoteDelayedNode'>
14
+
15
+ type DelayedNodePromotionPlanExecutorShape = DelayedNodePromotionPlanExecutorMethods
22
16
 
23
17
  export interface DelayedNodePromotionJob {
24
18
  runId: string
@@ -37,14 +31,13 @@ function processDelayedNodePromotionJob(
37
31
  deps: DelayedNodePromotionWorkerDeps,
38
32
  job: Job<DelayedNodePromotionJob>,
39
33
  ): Promise<void> {
40
- const { planExecutorService } = deps
41
- return Promise.resolve(
42
- planExecutorService.promoteDelayedNode({
34
+ return Effect.runPromise(
35
+ deps.planExecutorService.promoteDelayedNode({
43
36
  runId: job.data.runId,
44
37
  nodeId: job.data.nodeId,
45
38
  emittedBy: job.data.emittedBy,
46
39
  }),
47
- ).then(() => undefined)
40
+ )
48
41
  }
49
42
 
50
43
  export interface DelayedNodePromotionQueueRuntime {
@@ -82,6 +75,7 @@ export function makeDelayedNodePromotionQueueRuntime(
82
75
  }
83
76
 
84
77
  runStandaloneQueueWorker((runtime) => {
78
+ // @effect-diagnostics-next-line asyncFunction:off -- BullMQ standalone worker bootstrap.
85
79
  void (async () => {
86
80
  const { PlanExecutorServiceTag } = await import('../services/plan/plan-executor.service')
87
81
  const resolve = <I, T>(tag: Context.Key<I, T>): T => runtime.runSync(Effect.service(tag))
@@ -1,12 +1,18 @@
1
- import { Effect } from 'effect'
1
+ import { Effect, Schema } from 'effect'
2
2
  import type IORedis from 'ioredis'
3
3
 
4
4
  import type { chatLogger } from '../config/logger'
5
+ import { ERROR_TAGS } from '../effect/errors'
5
6
  import { sha256Hex } from '../utils/crypto'
6
7
  import { DEFAULT_JOB_RETENTION } from '../workers/worker-utils'
7
8
  import type { QueueJobService, WorkerHandle } from '../workers/worker-utils'
8
9
  import { createQueueFactory } from './queue-factory'
9
10
 
11
+ class DocumentProcessorEnqueueError extends Schema.TaggedErrorClass<DocumentProcessorEnqueueError>()(
12
+ ERROR_TAGS.QueueFactoryError,
13
+ { message: Schema.String, cause: Schema.Defect },
14
+ ) {}
15
+
10
16
  export type DocumentSourceChannel = string
11
17
 
12
18
  export interface DocumentProcessorAttachmentRef {
@@ -83,9 +89,12 @@ export function createDocumentProcessorQueueRuntime<TJob extends DocumentProcess
83
89
  enqueue: (job) => {
84
90
  return Effect.runPromise(
85
91
  Effect.gen(function* () {
86
- const queuedJob = yield* Effect.tryPromise(() =>
87
- queueRuntime.getQueue().add('process-document', job, { jobId: buildDocumentProcessorJobId(job) }),
88
- )
92
+ const queuedJob = yield* Effect.tryPromise({
93
+ try: () =>
94
+ queueRuntime.getQueue().add('process-document', job, { jobId: buildDocumentProcessorJobId(job) }),
95
+ catch: (cause) =>
96
+ new DocumentProcessorEnqueueError({ message: 'Failed to enqueue document processor job.', cause }),
97
+ })
89
98
 
90
99
  yield* Effect.catch(
91
100
  params.queueJobService.recordEnqueued({
@@ -1,8 +1,9 @@
1
- import { Effect } from 'effect'
1
+ import { Effect, Schema } from 'effect'
2
2
  import type { Context } from 'effect'
3
3
  import type IORedis from 'ioredis'
4
4
 
5
5
  import { serverLogger } from '../config/logger'
6
+ import { ERROR_TAGS } from '../effect/errors'
6
7
  import { RedisServiceTag } from '../effect/services'
7
8
  import { QueueJobServiceTag } from '../services/queue-job.service'
8
9
  import type { QueueJobService, WorkerHandle } from '../workers/worker-utils'
@@ -10,6 +11,11 @@ import { getWorkerPath, LONG_JOB_LOCK_DURATION_MS, LOW_JOB_RETENTION } from '../
10
11
  import { createQueueFactory } from './queue-factory'
11
12
  import { runStandaloneQueueWorker } from './standalone-worker'
12
13
 
14
+ class MemoryConsolidationSchedulerError extends Schema.TaggedErrorClass<MemoryConsolidationSchedulerError>()(
15
+ ERROR_TAGS.QueueFactoryError,
16
+ { message: Schema.String, cause: Schema.Defect },
17
+ ) {}
18
+
13
19
  export interface MemoryConsolidationJob {
14
20
  scopeId?: string
15
21
  }
@@ -50,19 +56,25 @@ export function makeMemoryConsolidationQueueRuntime(
50
56
  const scheduleRecurringConsolidation: MemoryConsolidationQueueRuntime['scheduleRecurringConsolidation'] = () =>
51
57
  Effect.runPromise(
52
58
  Effect.gen(function* () {
53
- const queuedJob = yield* Effect.tryPromise(() =>
54
- queue
55
- .getQueue()
56
- .upsertJobScheduler(
57
- MEMORY_CONSOLIDATION_SCHEDULER_ID,
58
- { every: MEMORY_CONSOLIDATION_INTERVAL_MS },
59
- {
60
- name: 'consolidate',
61
- data: {},
62
- opts: { ...LOW_JOB_RETENTION, attempts: 2, backoff: { type: 'exponential', delay: 5000 } },
63
- },
64
- ),
65
- )
59
+ const queuedJob = yield* Effect.tryPromise({
60
+ try: () =>
61
+ queue
62
+ .getQueue()
63
+ .upsertJobScheduler(
64
+ MEMORY_CONSOLIDATION_SCHEDULER_ID,
65
+ { every: MEMORY_CONSOLIDATION_INTERVAL_MS },
66
+ {
67
+ name: 'consolidate',
68
+ data: {},
69
+ opts: { ...LOW_JOB_RETENTION, attempts: 2, backoff: { type: 'exponential', delay: 5000 } },
70
+ },
71
+ ),
72
+ catch: (cause) =>
73
+ new MemoryConsolidationSchedulerError({
74
+ message: 'Failed to upsert memory consolidation scheduler.',
75
+ cause,
76
+ }),
77
+ })
66
78
 
67
79
  yield* Effect.catch(
68
80
  queueJobService.recordEnqueued({
@@ -5,19 +5,19 @@ import type IORedis from 'ioredis'
5
5
 
6
6
  import { serverLogger } from '../config/logger'
7
7
  import { DatabaseServiceTag, RedisServiceTag } from '../effect/services'
8
+ import type { makePlanAgentHeartbeatService } from '../services/plan/plan-agent-heartbeat.service'
8
9
  import { QueueJobServiceTag } from '../services/queue-job.service'
9
10
  import type { QueueJobService, WorkerHandle } from '../workers/worker-utils'
10
11
  import { DEFAULT_JOB_RETENTION, LONG_JOB_LOCK_DURATION_MS } from '../workers/worker-utils'
11
12
  import { createQueueFactoryWithDeps } from './queue-factory'
12
13
  import { runStandaloneQueueWorker } from './standalone-worker'
13
14
 
14
- // Minimal service shape used by the worker processor. Declared structurally to
15
- // avoid importing the service tag — which would form a dependency cycle since
16
- // PlanAgentHeartbeatServiceLive depends on LotaQueuesServiceTag.
17
- interface PlanAgentHeartbeatWorkerServiceShape {
18
- wakeNode(params: PlanAgentHeartbeatWakeJob): Effect.Effect<unknown, unknown, unknown>
19
- sweep(params: { organizationId?: string }): Effect.Effect<void, unknown, unknown>
20
- }
15
+ type PlanAgentHeartbeatWorkerServiceMethods = Pick<
16
+ ReturnType<typeof makePlanAgentHeartbeatService>,
17
+ 'wakeNode' | 'sweep'
18
+ >
19
+
20
+ type PlanAgentHeartbeatWorkerServiceShape = PlanAgentHeartbeatWorkerServiceMethods
21
21
 
22
22
  class PlanAgentHeartbeatQueueError extends Schema.TaggedErrorClass<PlanAgentHeartbeatQueueError>()(
23
23
  '@lota-sdk/core/PlanAgentHeartbeatQueueError',
@@ -95,7 +95,7 @@ export function makePlanAgentHeartbeatQueueRuntime(
95
95
  return Effect.runPromise(
96
96
  Effect.gen(function* () {
97
97
  if (job.data.type === 'wake-node') {
98
- const wakeJob = job.data
98
+ const wakeJob: PlanAgentHeartbeatWakeJob = job.data
99
99
  yield* service.wakeNode(wakeJob)
100
100
  return
101
101
  }
@@ -111,7 +111,7 @@ export function makePlanAgentHeartbeatQueueRuntime(
111
111
  }),
112
112
  })
113
113
  }
114
- }) as Effect.Effect<void, never, never>,
114
+ }),
115
115
  )
116
116
  }
117
117
 
@@ -148,6 +148,7 @@ export function makePlanAgentHeartbeatQueueRuntime(
148
148
  }
149
149
 
150
150
  runStandaloneQueueWorker((runtime) => {
151
+ // @effect-diagnostics-next-line asyncFunction:off -- BullMQ standalone worker bootstrap.
151
152
  void (async () => {
152
153
  const { PlanAgentHeartbeatServiceTag } = await import('../services/plan/plan-agent-heartbeat.service')
153
154
  const resolve = <I, T>(tag: Context.Key<I, T>): T => runtime.runSync(Effect.service(tag))