@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,4 +1,3 @@
1
- import { isAgentName } from '../config/agent-defaults'
2
1
  import { compactWhitespace, readRecord, readString } from '../utils/string'
3
2
  import type { DigestMessage } from './utils/thread-message-query'
4
3
 
@@ -26,7 +25,7 @@ function normalizeFilePartMetadata(part: DigestMessagePart): string | null {
26
25
 
27
26
  function extractAssistantLabel(
28
27
  message: DigestMessageForTranscript,
29
- isKnownAgentName: (value: string) => boolean = isAgentName,
28
+ isKnownAgentName: (value: string) => boolean,
30
29
  ): string {
31
30
  const metadataAgentId =
32
31
  typeof message.metadata?.agentId === 'string' ? message.metadata.agentId.trim().toLowerCase() : ''
@@ -44,11 +43,11 @@ function extractAssistantLabel(
44
43
 
45
44
  export function buildDigestTranscript(params: {
46
45
  messages: DigestMessageForTranscript[]
47
- isKnownAgentName?: (value: string) => boolean
46
+ isKnownAgentName: (value: string) => boolean
48
47
  }): { transcript: string; involvedAgentNames: string[] } {
49
48
  const lines: string[] = []
50
49
  const involvedAgentNames = new Set<string>()
51
- const isKnownAgentName = params.isKnownAgentName ?? isAgentName
50
+ const { isKnownAgentName } = params
52
51
 
53
52
  for (const message of params.messages) {
54
53
  if (message.role !== 'user' && message.role !== 'assistant') continue
@@ -1,19 +1,20 @@
1
- import { Cause, Effect } from 'effect'
1
+ import { Effect, Schema } from 'effect'
2
2
  import type { Context } from 'effect'
3
3
  import { BoundQuery } from 'surrealdb'
4
4
  import { z } from 'zod'
5
5
 
6
+ import type { ResolvedAgentConfig } from '../config/agent-defaults'
7
+ import { isAgentName } from '../config/agent-defaults'
6
8
  import { serverLogger } from '../config/logger'
7
9
  import { ensureRecordId, recordIdToString } from '../db/record-id'
8
10
  import type { RecordIdRef } from '../db/record-id'
9
11
  import type { SurrealDBService } from '../db/service'
10
12
  import { TABLES } from '../db/tables'
11
13
  import { effectTryPromise } from '../effect/helpers'
12
- import {
13
- clearRegularChatMemoryDigestDeduplicationKey,
14
- enqueueRegularChatMemoryDigest,
14
+ import type {
15
+ OrganizationLearningQueueRuntime,
16
+ RegularChatMemoryDigestJob,
15
17
  } from '../queues/organization-learning.queue'
16
- import type { RegularChatMemoryDigestJob } from '../queues/organization-learning.queue'
17
18
  import { createHelperModelRuntime } from '../runtime/helper-model'
18
19
  import type { LotaRuntimeAdapters, LotaRuntimeBackgroundCursor } from '../runtime/runtime-extensions'
19
20
  import type { MemoryServiceTag } from '../services/memory/memory.service'
@@ -35,13 +36,20 @@ import type { DigestMessage } from './utils/thread-message-query'
35
36
  // can be digested into durable memory and profile projections in the background.
36
37
  const StructuredProfilePatchSchema = z.record(z.string(), z.unknown()).default({})
37
38
 
39
+ class MemoryDigestError extends Schema.TaggedErrorClass<MemoryDigestError>()('MemoryDigestError', {
40
+ message: Schema.String,
41
+ cause: Schema.Defect,
42
+ }) {}
43
+
38
44
  const REGULAR_CHAT_MEMORY_DIGEST_TIMEOUT_MS = 10 * 60 * 1000
39
45
  const WorkspaceMemoryRowSchema = z.object({ content: z.string() })
40
46
  export interface RegularChatDigestServices {
47
+ agentConfig: ResolvedAgentConfig
41
48
  databaseService: SurrealDBService
42
49
  memoryService: Context.Service.Shape<typeof MemoryServiceTag>
43
50
  socialChatHistoryService: Context.Service.Shape<typeof SocialChatHistoryServiceTag>
44
51
  runtimeAdapters: LotaRuntimeAdapters
52
+ organizationLearningQueue: OrganizationLearningQueueRuntime
45
53
  }
46
54
 
47
55
  const ExtractedFactSchema = z.object({
@@ -120,11 +128,9 @@ function hasNewEligibleThreadMessages(params: {
120
128
  Effect.gen(function* () {
121
129
  if (params.threadIds.length === 0) return false
122
130
 
123
- let query: BoundQuery | null = null
124
- if (params.cursor) {
125
- const cursorRowId = ensureRecordId(params.cursor.id, TABLES.THREAD_MESSAGE)
126
- query = new BoundQuery(
127
- `SELECT id, createdAt FROM ${TABLES.THREAD_MESSAGE}
131
+ const query: BoundQuery | null = params.cursor
132
+ ? new BoundQuery(
133
+ `SELECT id, createdAt FROM ${TABLES.THREAD_MESSAGE}
128
134
  WHERE threadId IN $threadIds
129
135
  AND (
130
136
  createdAt > $cursorCreatedAt
@@ -132,18 +138,22 @@ function hasNewEligibleThreadMessages(params: {
132
138
  )
133
139
  ORDER BY createdAt ASC, id ASC
134
140
  LIMIT 1`,
135
- { threadIds: params.threadIds, cursorCreatedAt: params.cursor.createdAt, cursorRowId },
136
- )
137
- } else if (params.onboardingCutoff) {
138
- query = new BoundQuery(
139
- `SELECT id, createdAt FROM ${TABLES.THREAD_MESSAGE}
141
+ {
142
+ threadIds: params.threadIds,
143
+ cursorCreatedAt: params.cursor.createdAt,
144
+ cursorRowId: ensureRecordId(params.cursor.id, TABLES.THREAD_MESSAGE),
145
+ },
146
+ )
147
+ : params.onboardingCutoff
148
+ ? new BoundQuery(
149
+ `SELECT id, createdAt FROM ${TABLES.THREAD_MESSAGE}
140
150
  WHERE threadId IN $threadIds
141
151
  AND createdAt > $onboardingCutoff
142
152
  ORDER BY createdAt ASC, id ASC
143
153
  LIMIT 1`,
144
- { threadIds: params.threadIds, onboardingCutoff: params.onboardingCutoff },
145
- )
146
- }
154
+ { threadIds: params.threadIds, onboardingCutoff: params.onboardingCutoff },
155
+ )
156
+ : null
147
157
 
148
158
  if (!query) return false
149
159
  const rows = yield* effectTryPromise(() => params.db.query<unknown>(query))
@@ -233,7 +243,10 @@ function runRegularChatMemoryDigestEffect(
233
243
  }
234
244
 
235
245
  const combinedMessages = [...threadMessages, ...socialMessages].sort(compareDigestMessageOrder)
236
- const { transcript, involvedAgentNames } = buildDigestTranscript({ messages: combinedMessages })
246
+ const { transcript, involvedAgentNames } = buildDigestTranscript({
247
+ messages: combinedMessages,
248
+ isKnownAgentName: (value: string) => isAgentName(services.agentConfig, value),
249
+ })
237
250
  const existingMemories = yield* effectTryPromise(() =>
238
251
  loadExistingOrganizationMemories(services.databaseService, orgId),
239
252
  )
@@ -261,7 +274,10 @@ function runRegularChatMemoryDigestEffect(
261
274
 
262
275
  const summaryBlock = normalizeBlock(synthesis.summaryBlock)
263
276
  if (!summaryBlock) {
264
- return yield* new Cause.UnknownError(new Error('Regular chat memory digest returned an empty summaryBlock'))
277
+ return yield* new MemoryDigestError({
278
+ message: 'Regular chat memory digest returned an empty summaryBlock',
279
+ cause: new Error('Regular chat memory digest returned an empty summaryBlock'),
280
+ })
265
281
  }
266
282
 
267
283
  const processedThreadCursor = getLastCursor(threadMessages)
@@ -321,8 +337,10 @@ function runRegularChatMemoryDigestEffect(
321
337
 
322
338
  const followUpScheduled = hasMoreThreadMessages || hasMoreSocialMessages
323
339
  if (followUpScheduled) {
324
- yield* effectTryPromise(() => clearRegularChatMemoryDigestDeduplicationKey(orgId))
325
- yield* effectTryPromise(() => enqueueRegularChatMemoryDigest({ orgId }))
340
+ yield* effectTryPromise(() =>
341
+ services.organizationLearningQueue.clearRegularChatMemoryDigestDeduplicationKey(orgId),
342
+ )
343
+ yield* effectTryPromise(() => services.organizationLearningQueue.enqueueRegularChatMemoryDigest({ orgId }))
326
344
  }
327
345
 
328
346
  serverLogger.info`Regular chat memory digest completed for ${orgId}: threadMessages=${threadMessages.length}, socialMessages=${socialMessages.length}, facts=${synthesis.facts.length}, followUpScheduled=${followUpScheduled}`
@@ -340,7 +358,7 @@ export function runRegularChatMemoryDigest(
340
358
  data: RegularChatMemoryDigestJob,
341
359
  services: RegularChatDigestServices,
342
360
  ): Promise<RegularChatDigestRunResult> {
343
- const { databaseService, memoryService, socialChatHistoryService, runtimeAdapters } = services
361
+ const { runtimeAdapters } = services
344
362
  const orgRef = ensureRecordId(data.orgId, TABLES.ORGANIZATION)
345
363
  const orgId = recordIdToString(orgRef, TABLES.ORGANIZATION)
346
364
  const workspaceProvider = runtimeAdapters.workspaceProvider
@@ -357,12 +375,11 @@ export function runRegularChatMemoryDigest(
357
375
  const withMemoryLock = runtimeAdapters.withWorkspaceMemoryLock
358
376
  const runDigest = () =>
359
377
  Effect.runPromise(
360
- runRegularChatMemoryDigestEffect(
361
- { databaseService, memoryService, socialChatHistoryService, runtimeAdapters },
362
- orgRef,
363
- orgId,
364
- workspaceProvider,
365
- ),
378
+ runRegularChatMemoryDigestEffect(services, orgRef, orgId, workspaceProvider) as Effect.Effect<
379
+ RegularChatDigestRunResult,
380
+ never,
381
+ never
382
+ >,
366
383
  )
367
384
 
368
385
  return withMemoryLock ? withMemoryLock(orgId, runDigest) : runDigest()
@@ -1,6 +1,8 @@
1
1
  import type { Context, Cause } from 'effect'
2
2
  import { Effect } from 'effect'
3
3
 
4
+ import type { ResolvedAgentConfig } from '../config/agent-defaults'
5
+ import { isAgentName } from '../config/agent-defaults'
4
6
  import { serverLogger } from '../config/logger'
5
7
  import { ensureRecordId, recordIdToString } from '../db/record-id'
6
8
  import type { RecordIdRef } from '../db/record-id'
@@ -27,6 +29,7 @@ const SKILL_EXTRACTION_TIMEOUT_MS = 10 * 60 * 1000
27
29
  const MIN_MESSAGE_THRESHOLD = 10
28
30
 
29
31
  export interface SkillExtractionServices {
32
+ agentConfig: ResolvedAgentConfig
30
33
  databaseService: SurrealDBService
31
34
  learnedSkillService: Context.Service.Shape<typeof LearnedSkillServiceTag>
32
35
  socialChatHistoryService: Context.Service.Shape<typeof SocialChatHistoryServiceTag>
@@ -149,7 +152,10 @@ function runSkillExtractionEffect(
149
152
  }
150
153
 
151
154
  const sortedMessages = [...messages].sort(compareDigestMessageOrder)
152
- const { transcript } = buildDigestTranscript({ messages: sortedMessages })
155
+ const { transcript } = buildDigestTranscript({
156
+ messages: sortedMessages,
157
+ isKnownAgentName: (value: string) => isAgentName(services.agentConfig, value),
158
+ })
153
159
 
154
160
  const existingSkills = yield* services.learnedSkillService.listForOrg(orgId)
155
161
  const existingSkillsSummary =
@@ -301,7 +307,7 @@ export function runSkillExtraction(
301
307
  data: SkillExtractionJob,
302
308
  services: SkillExtractionServices,
303
309
  ): Promise<SkillExtractionRunResult> {
304
- const { databaseService, learnedSkillService, socialChatHistoryService, runtimeAdapters } = services
310
+ const { runtimeAdapters } = services
305
311
  const orgRef = ensureRecordId(data.orgId, TABLES.ORGANIZATION)
306
312
  const orgId = recordIdToString(orgRef, TABLES.ORGANIZATION)
307
313
  const workspaceProvider = runtimeAdapters.workspaceProvider
@@ -317,19 +323,11 @@ export function runSkillExtraction(
317
323
  const withMemoryLock = runtimeAdapters.withWorkspaceMemoryLock
318
324
  const runExtraction = () =>
319
325
  Effect.runPromise(
320
- runSkillExtractionEffect(
321
- {
322
- databaseService,
323
- learnedSkillService,
324
- socialChatHistoryService,
325
- runtimeAdapters,
326
- embeddingModel: services.embeddingModel,
327
- },
328
- orgRef,
329
- orgId,
330
- workspaceProvider,
331
- embeddings,
332
- ),
326
+ runSkillExtractionEffect(services, orgRef, orgId, workspaceProvider, embeddings) as Effect.Effect<
327
+ SkillExtractionRunResult,
328
+ never,
329
+ never
330
+ >,
333
331
  )
334
332
 
335
333
  return withMemoryLock ? withMemoryLock(orgId, runExtraction) : runExtraction()
@@ -5,12 +5,9 @@ import { Effect } from 'effect'
5
5
  import type { Context } from 'effect'
6
6
 
7
7
  import { chatLogger } from '../config/logger'
8
- import { getCurrentRuntime } from '../effect/runtime-ref'
9
- import { QueueJobServiceTag } from '../services/queue-job.service'
8
+ import type { QueueJobServiceTag } from '../services/queue-job.service'
10
9
 
11
- export function getQueueJobService(): Context.Service.Shape<typeof QueueJobServiceTag> {
12
- return getCurrentRuntime().runSync(Effect.service(QueueJobServiceTag))
13
- }
10
+ export type QueueJobService = Context.Service.Shape<typeof QueueJobServiceTag>
14
11
 
15
12
  export const DEFAULT_JOB_RETENTION = { removeOnComplete: true, removeOnFail: { age: 24 * 60 * 60, count: 200 } }
16
13
  export const LOW_JOB_RETENTION = { removeOnComplete: true, removeOnFail: { age: 6 * 60 * 60, count: 50 } }
@@ -88,6 +85,7 @@ export const createWorkerShutdown = (worker: Worker, name: string, logger: typeo
88
85
  export function createTracedWorkerProcessor<TJob extends TracedWorkerJobLike, TResult = void>(
89
86
  queueName: string,
90
87
  processor: (job: TJob) => Promise<TResult>,
88
+ queueJobService: QueueJobService,
91
89
  ): (job: TJob) => Promise<TResult> {
92
90
  return (job: TJob) => {
93
91
  const trackedJob = {
@@ -107,7 +105,7 @@ export function createTracedWorkerProcessor<TJob extends TracedWorkerJobLike, TR
107
105
  return Effect.runPromise(
108
106
  Effect.catch(
109
107
  Effect.gen(function* () {
110
- yield* Effect.catch(getQueueJobService().markAttemptStarted(trackedJob), (error) =>
108
+ yield* Effect.catch(queueJobService.markAttemptStarted(trackedJob), (error) =>
111
109
  Effect.sync(() => {
112
110
  logPersistenceError('start', error)
113
111
  }),
@@ -115,7 +113,7 @@ export function createTracedWorkerProcessor<TJob extends TracedWorkerJobLike, TR
115
113
 
116
114
  const result = yield* Effect.tryPromise(() => processor(job))
117
115
 
118
- yield* Effect.catch(getQueueJobService().markAttemptCompleted(trackedJob, result), (error) =>
116
+ yield* Effect.catch(queueJobService.markAttemptCompleted(trackedJob, result), (error) =>
119
117
  Effect.sync(() => {
120
118
  logPersistenceError('completion', error)
121
119
  }),
@@ -125,13 +123,21 @@ export function createTracedWorkerProcessor<TJob extends TracedWorkerJobLike, TR
125
123
  }),
126
124
  (error) =>
127
125
  Effect.gen(function* () {
128
- yield* Effect.catch(getQueueJobService().markAttemptFailed(trackedJob, error), (persistenceError) =>
126
+ yield* Effect.catch(queueJobService.markAttemptFailed(trackedJob, error), (persistenceError) =>
129
127
  Effect.sync(() => {
130
128
  logPersistenceError('failure', persistenceError)
131
129
  }),
132
130
  )
133
131
  return yield* error
134
132
  }),
133
+ ).pipe(
134
+ Effect.withSpan(`worker.${queueName}.${job.name}`),
135
+ Effect.annotateSpans({
136
+ 'job.id': trackedJob.id !== undefined ? String(trackedJob.id) : 'unknown',
137
+ 'job.name': job.name,
138
+ 'job.attemptsMade': typeof job.attemptsMade === 'number' ? job.attemptsMade : -1,
139
+ 'queue.name': queueName,
140
+ }),
135
141
  ),
136
142
  )
137
143
  }
@@ -1,3 +0,0 @@
1
- export { VECTOR_SEARCH_OVERFETCH_MULTIPLIER } from '@lota-sdk/shared'
2
-
3
- export const DEFAULT_MEMORY_SEARCH_LIMIT = 10
@@ -1,87 +0,0 @@
1
- import { Effect } from 'effect'
2
-
3
- const awaitableEffectMarker = Symbol('AwaitableEffect')
4
-
5
- type AwaitableEffectState<A> = { promise?: Promise<A> }
6
-
7
- export type AwaitableEffect<A, E> = Effect.Effect<A, E, never> & Promise<A>
8
-
9
- export type AwaitableValue<T> = T extends (...args: infer TArgs) => Effect.Effect<infer A, infer E, never>
10
- ? (...args: TArgs) => AwaitableEffect<A, E>
11
- : T extends (...args: infer TArgs) => infer TResult
12
- ? (...args: TArgs) => TResult
13
- : T
14
-
15
- type AwaitableServiceMethods<T> = {
16
- [K in keyof T]: AwaitableValue<T[K]>
17
- }
18
-
19
- export type AwaitableService<T> = AwaitableServiceMethods<T>
20
-
21
- export type MaybeAwaitableService<T extends object> = T | AwaitableService<T>
22
-
23
- type AwaitableEffectOptions = { runPromise?: <A, E>(effect: Effect.Effect<A, E, never>) => Promise<A> }
24
-
25
- export function toAwaitableEffect<A, E>(
26
- effect: Effect.Effect<A, E, never>,
27
- options?: AwaitableEffectOptions,
28
- ): AwaitableEffect<A, E> {
29
- const existing = effect as AwaitableEffect<A, E> & { [awaitableEffectMarker]?: AwaitableEffectState<A> }
30
-
31
- if (existing[awaitableEffectMarker]) {
32
- return existing
33
- }
34
-
35
- const state: AwaitableEffectState<A> = {}
36
- const runPromise = options?.runPromise ?? Effect.runPromise
37
- const ensurePromise = () => (state.promise ??= runPromise(effect))
38
- const candidate = Object.create(
39
- Object.getPrototypeOf(effect),
40
- Object.getOwnPropertyDescriptors(effect),
41
- ) as AwaitableEffect<A, E> & { [awaitableEffectMarker]?: AwaitableEffectState<A> }
42
-
43
- const then: Promise<A>['then'] = (onfulfilled, onrejected) => ensurePromise().then(onfulfilled, onrejected)
44
- const catchMethod: Promise<A>['catch'] = (onrejected) => ensurePromise().catch(onrejected)
45
- const finallyMethod: Promise<A>['finally'] = (onfinally) => ensurePromise().finally(onfinally)
46
-
47
- void Object.defineProperties(candidate, {
48
- then: { value: then, configurable: true },
49
- catch: { value: catchMethod, configurable: true },
50
- finally: { value: finallyMethod, configurable: true },
51
- [Symbol.toStringTag]: { value: 'Promise', configurable: true },
52
- [awaitableEffectMarker]: { value: state },
53
- })
54
-
55
- return candidate
56
- }
57
-
58
- export function toAwaitableService<T extends object>(
59
- service: T,
60
- options?: AwaitableEffectOptions,
61
- ): AwaitableService<T> {
62
- const wrappedMethods = new Map<PropertyKey, unknown>()
63
-
64
- return new Proxy(service, {
65
- get(target, property, receiver) {
66
- const value = Reflect.get(target, property, receiver)
67
- if (typeof value !== 'function') {
68
- return value
69
- }
70
-
71
- const existing = wrappedMethods.get(property)
72
- if (existing !== undefined) {
73
- return existing
74
- }
75
-
76
- const wrapped = (...args: unknown[]) => {
77
- const result = Reflect.apply(value, target, args)
78
- return Effect.isEffect(result)
79
- ? toAwaitableEffect(result as Effect.Effect<unknown, unknown, never>, options)
80
- : result
81
- }
82
-
83
- wrappedMethods.set(property, wrapped)
84
- return wrapped
85
- },
86
- }) as AwaitableService<T>
87
- }
@@ -1,25 +0,0 @@
1
- import type { ManagedRuntime } from 'effect'
2
-
3
- // eslint-disable-next-line typescript-eslint/no-explicit-any -- ManagedRuntime is contravariant in R; `any` is the only valid wildcard
4
- type SdkManagedRuntime = ManagedRuntime.ManagedRuntime<any, any>
5
-
6
- let currentRuntime: SdkManagedRuntime | null = null
7
-
8
- export function setCurrentRuntime<R, E>(runtime: ManagedRuntime.ManagedRuntime<R, E>): void {
9
- currentRuntime = runtime as SdkManagedRuntime
10
- }
11
-
12
- export function clearCurrentRuntime(): void {
13
- currentRuntime = null
14
- }
15
-
16
- export function getCurrentRuntime(): SdkManagedRuntime {
17
- if (!currentRuntime) {
18
- throw new Error('Lota Effect runtime is not configured. Call createLotaRuntime() first.')
19
- }
20
- return currentRuntime
21
- }
22
-
23
- export function getOptionalCurrentRuntime(): SdkManagedRuntime | null {
24
- return currentRuntime
25
- }
@@ -1,31 +0,0 @@
1
- import type { Effect, ManagedRuntime } from 'effect'
2
-
3
- import { clearCurrentRuntime, getCurrentRuntime, getOptionalCurrentRuntime, setCurrentRuntime } from './runtime-ref'
4
-
5
- export function setLotaSdkRuntime<R, E>(runtime: ManagedRuntime.ManagedRuntime<R, E>): void {
6
- setCurrentRuntime(runtime)
7
- }
8
-
9
- export function clearLotaSdkRuntime(): void {
10
- clearCurrentRuntime()
11
- }
12
-
13
- export function getOptionalLotaSdkRuntime() {
14
- return getOptionalCurrentRuntime()
15
- }
16
-
17
- /** Returns the current managed runtime or throws. */
18
- export function getLotaSdkRuntime() {
19
- return getCurrentRuntime()
20
- }
21
-
22
- /**
23
- * Run an effect as a Promise using the current managed runtime's context.
24
- * The runtime must be initialized via `createLotaRuntime()` before any call.
25
- */
26
- export function runPromise<A, E>(
27
- effect: Effect.Effect<A, E, never>,
28
- options?: { readonly signal?: AbortSignal },
29
- ): Promise<A> {
30
- return getCurrentRuntime().runPromise(effect, options)
31
- }
@@ -1,10 +0,0 @@
1
- import { Effect } from 'effect'
2
- import type IORedis from 'ioredis'
3
-
4
- import { getCurrentRuntime } from '../effect/runtime-ref'
5
- import { RedisServiceTag } from '../effect/services'
6
-
7
- export function getRuntimeRedisConnection(): IORedis {
8
- const redis = getCurrentRuntime().runSync(Effect.service(RedisServiceTag))
9
- return redis.getConnection()
10
- }
@@ -1 +0,0 @@
1
- export type { ChatMode, CreateHelperToolLoopAgentOptions, CreateRoutedAgentOptions } from '@lota-sdk/shared'