@lota-sdk/core 0.4.12 → 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 (139) hide show
  1. package/package.json +4 -4
  2. package/src/ai/embedding-cache.ts +17 -11
  3. package/src/ai-gateway/ai-gateway.ts +164 -94
  4. package/src/ai-gateway/index.ts +4 -1
  5. package/src/config/agent-defaults.ts +2 -2
  6. package/src/config/agent-types.ts +1 -1
  7. package/src/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/live-turn-trace.ts +6 -49
  37. package/src/runtime/memory/memory-block.ts +3 -9
  38. package/src/runtime/memory/memory-scope.ts +3 -1
  39. package/src/runtime/plugin-resolution.ts +2 -1
  40. package/src/runtime/post-turn-side-effects.ts +6 -5
  41. package/src/runtime/retrieval-adapters.ts +8 -20
  42. package/src/runtime/runtime-config.ts +3 -9
  43. package/src/runtime/runtime-extensions.ts +2 -4
  44. package/src/runtime/runtime-lifecycle.ts +56 -16
  45. package/src/runtime/runtime-services.ts +180 -102
  46. package/src/runtime/runtime-worker-registry.ts +3 -1
  47. package/src/runtime/social-chat/social-chat-agent-runner.ts +1 -1
  48. package/src/runtime/social-chat/social-chat-history.ts +21 -18
  49. package/src/runtime/social-chat/social-chat.ts +356 -223
  50. package/src/runtime/specialist-runner.ts +3 -1
  51. package/src/runtime/team-consultation/team-consultation-orchestrator.ts +3 -2
  52. package/src/runtime/thread-turn-context.ts +142 -102
  53. package/src/runtime/turn-lifecycle.ts +15 -46
  54. package/src/services/agent-activity.service.ts +1 -1
  55. package/src/services/agent-executor.service.ts +107 -77
  56. package/src/services/autonomous-job.service.ts +354 -293
  57. package/src/services/background-work.service.ts +3 -3
  58. package/src/services/context-compaction.service.ts +7 -2
  59. package/src/services/document-chunk.service.ts +50 -32
  60. package/src/services/execution-plan/execution-plan-schedule.ts +5 -3
  61. package/src/services/execution-plan/execution-plan.service.ts +162 -179
  62. package/src/services/feedback-loop.service.ts +5 -4
  63. package/src/services/graph-full-routing.ts +37 -36
  64. package/src/services/institutional-memory.service.ts +28 -30
  65. package/src/services/learned-skill.service.ts +107 -72
  66. package/src/services/memory/memory-errors.ts +4 -23
  67. package/src/services/memory/memory-org-memory.ts +10 -5
  68. package/src/services/memory/memory-rerank.ts +18 -6
  69. package/src/services/memory/memory.service.ts +170 -111
  70. package/src/services/memory/rerank.service.ts +29 -20
  71. package/src/services/organization-member.service.ts +1 -1
  72. package/src/services/organization.service.ts +69 -75
  73. package/src/services/ownership-dispatcher.service.ts +40 -39
  74. package/src/services/plan/plan-agent-heartbeat.service.ts +26 -23
  75. package/src/services/plan/plan-agent-query.service.ts +39 -31
  76. package/src/services/plan/plan-completion-side-effects.ts +13 -17
  77. package/src/services/plan/plan-coordination.service.ts +2 -1
  78. package/src/services/plan/plan-cycle.service.ts +6 -5
  79. package/src/services/plan/plan-deadline.service.ts +57 -54
  80. package/src/services/plan/plan-event-delivery.service.ts +5 -4
  81. package/src/services/plan/plan-executor-graph.ts +18 -15
  82. package/src/services/plan/plan-executor.service.ts +235 -262
  83. package/src/services/plan/plan-run.service.ts +169 -93
  84. package/src/services/plan/plan-scheduler.service.ts +192 -202
  85. package/src/services/plan/plan-template.service.ts +1 -1
  86. package/src/services/plan/plan-transaction-events.ts +1 -1
  87. package/src/services/plan/plan-workspace.service.ts +23 -14
  88. package/src/services/plugin-executor.service.ts +5 -9
  89. package/src/services/queue-job.service.ts +117 -59
  90. package/src/services/recent-activity-title.service.ts +13 -12
  91. package/src/services/recent-activity.service.ts +6 -1
  92. package/src/services/social-chat-history.service.ts +29 -25
  93. package/src/services/system-executor.service.ts +5 -9
  94. package/src/services/thread/thread-active-run.ts +2 -2
  95. package/src/services/thread/thread-listing.ts +61 -57
  96. package/src/services/thread/thread-memory-block.ts +73 -48
  97. package/src/services/thread/thread-message.service.ts +76 -65
  98. package/src/services/thread/thread-record-store.ts +8 -8
  99. package/src/services/thread/thread-title.service.ts +10 -4
  100. package/src/services/thread/thread-turn-execution.ts +43 -45
  101. package/src/services/thread/thread-turn-preparation.service.ts +257 -135
  102. package/src/services/thread/thread-turn-streaming.ts +82 -85
  103. package/src/services/thread/thread-turn.ts +8 -8
  104. package/src/services/thread/thread.service.ts +135 -100
  105. package/src/services/user.service.ts +45 -48
  106. package/src/storage/attachment-parser.ts +6 -2
  107. package/src/storage/attachment-storage.service.ts +5 -6
  108. package/src/storage/generated-document-storage.service.ts +1 -1
  109. package/src/system-agents/context-compaction.agent.ts +10 -9
  110. package/src/system-agents/delegated-agent-factory.ts +30 -6
  111. package/src/system-agents/memory-reranker.agent.ts +10 -9
  112. package/src/system-agents/memory.agent.ts +10 -9
  113. package/src/system-agents/recent-activity-title-refiner.agent.ts +13 -15
  114. package/src/system-agents/regular-chat-memory-digest.agent.ts +13 -12
  115. package/src/system-agents/skill-extractor.agent.ts +13 -12
  116. package/src/system-agents/skill-manager.agent.ts +13 -12
  117. package/src/system-agents/thread-router.agent.ts +10 -5
  118. package/src/system-agents/title-generator.agent.ts +13 -12
  119. package/src/tools/fetch-webpage.tool.ts +13 -13
  120. package/src/tools/memory-block.tool.ts +3 -1
  121. package/src/tools/plan-approval.tool.ts +4 -2
  122. package/src/tools/read-file-parts.tool.ts +10 -4
  123. package/src/tools/remember-memory.tool.ts +3 -1
  124. package/src/tools/research-topic.tool.ts +9 -5
  125. package/src/tools/search-web.tool.ts +16 -16
  126. package/src/tools/search.tool.ts +20 -5
  127. package/src/tools/team-think.tool.ts +61 -38
  128. package/src/utils/async.ts +5 -5
  129. package/src/utils/errors.ts +19 -18
  130. package/src/utils/sse-keepalive.ts +28 -25
  131. package/src/workers/bootstrap.ts +75 -11
  132. package/src/workers/memory-consolidation.worker.ts +82 -91
  133. package/src/workers/organization-learning.worker.ts +14 -4
  134. package/src/workers/regular-chat-memory-digest.runner.ts +105 -67
  135. package/src/workers/skill-extraction.runner.ts +97 -61
  136. package/src/workers/utils/repo-structure-extractor.ts +13 -8
  137. package/src/workers/utils/thread-message-query.ts +24 -24
  138. package/src/workers/worker-utils.ts +23 -4
  139. package/src/effect/helpers.ts +0 -123
@@ -1,7 +1,9 @@
1
1
  import type { ToolSet } from 'ai'
2
2
  import { Schema, Effect } from 'effect'
3
3
 
4
- class SpecialistRunnerError extends Schema.TaggedErrorClass<SpecialistRunnerError>()('SpecialistRunnerError', {
4
+ import { ERROR_TAGS } from '../effect/errors'
5
+
6
+ class SpecialistRunnerError extends Schema.TaggedErrorClass<SpecialistRunnerError>()(ERROR_TAGS.SpecialistRunnerError, {
5
7
  message: Schema.String,
6
8
  cause: Schema.optional(Schema.Defect),
7
9
  }) {}
@@ -4,6 +4,7 @@ import { convertToModelMessages, tool as createTool } from 'ai'
4
4
  import { Schema, Deferred, Effect, Exit, Fiber, Queue, Ref, Scope } from 'effect'
5
5
 
6
6
  import type { ResolvedAgentConfig } from '../../config/agent-defaults'
7
+ import { ERROR_TAGS } from '../../effect/errors'
7
8
  import { nowEpochMillis } from '../../utils/date-time'
8
9
  import { createTimedAbortSignal } from '../agent-stream-helpers'
9
10
  import { buildModelInputMessagesWithUploadMetadata, buildReadableUploadMetadataText } from '../chat-attachments'
@@ -15,7 +16,7 @@ import { buildTeamConsultationFailureMessage } from './team-consultation-prompts
15
16
  export type DefaultRepoSections = RepoSectionName[]
16
17
  const TEAM_CONSULTATION_TIMEOUT_MS = 90_000
17
18
 
18
- class TeamConsultationError extends Schema.TaggedErrorClass<TeamConsultationError>()('TeamConsultationError', {
19
+ class TeamConsultationError extends Schema.TaggedErrorClass<TeamConsultationError>()(ERROR_TAGS.TeamConsultationError, {
19
20
  message: Schema.String,
20
21
  cause: Schema.optional(Schema.Defect),
21
22
  }) {}
@@ -62,7 +63,7 @@ function selectTeamConsultationContextMessages(messages: ChatMessage[], latestUs
62
63
  }
63
64
 
64
65
  interface ParticipantObserver {
65
- run<T>(fn: () => T | Promise<T>): Promise<T>
66
+ run<T>(fn: () => Promise<T>): Promise<T>
66
67
  recordError?: (error: unknown) => void
67
68
  recordAbort?: (error: unknown) => void
68
69
  }
@@ -1,7 +1,7 @@
1
1
  import { Schema, Effect } from 'effect'
2
2
 
3
3
  import type { RecordIdRef } from '../db/record-id'
4
- import { effectTryMaybeAsync as effectTryMaybeAsyncShared, makeEffectTryPromiseWithMessage } from '../effect/helpers'
4
+ import { ERROR_TAGS } from '../effect/errors'
5
5
  import { buildAgentPromptContext } from './agent-prompt-context'
6
6
  import {
7
7
  buildIndexedRepositoriesContext,
@@ -24,20 +24,13 @@ function isRecord(value: unknown): value is Record<string, unknown> {
24
24
  return typeof value === 'object' && value !== null
25
25
  }
26
26
 
27
- class ThreadTurnContextError extends Schema.TaggedErrorClass<ThreadTurnContextError>()('ThreadTurnContextError', {
28
- message: Schema.String,
29
- cause: Schema.optional(Schema.Defect),
30
- }) {}
27
+ class ThreadTurnContextError extends Schema.TaggedErrorClass<ThreadTurnContextError>()(
28
+ ERROR_TAGS.ThreadTurnContextError,
29
+ { message: Schema.String, cause: Schema.optional(Schema.Defect) },
30
+ ) {}
31
31
 
32
- const effectTryPromise = makeEffectTryPromiseWithMessage(
33
- (message, cause) => new ThreadTurnContextError({ message, cause }),
34
- )
35
-
36
- function effectTryMaybeAsync<A>(
37
- evaluate: () => A | PromiseLike<A>,
38
- message: string,
39
- ): Effect.Effect<A, ThreadTurnContextError> {
40
- return effectTryMaybeAsyncShared(evaluate, (cause) => new ThreadTurnContextError({ message, cause }))
32
+ function toThreadTurnContextError(message: string, cause: unknown): ThreadTurnContextError {
33
+ return new ThreadTurnContextError({ message, cause })
41
34
  }
42
35
 
43
36
  export const assembleThreadTurnContext = Effect.fn('ThreadTurnContext.assemble')(function* (params: {
@@ -55,38 +48,56 @@ export const assembleThreadTurnContext = Effect.fn('ThreadTurnContext.assemble')
55
48
  runtimeAdapters: LotaRuntimeAdapters
56
49
  pluginRuntime?: Record<string, unknown>
57
50
  }) {
58
- const workspace = yield* effectTryPromise(() => params.workspacePromise, 'Failed to load thread workspace').pipe(
59
- Effect.withSpan('ThreadTurnContext.loadWorkspace'),
60
- )
51
+ const workspace = yield* Effect.tryPromise({
52
+ try: () => params.workspacePromise,
53
+ catch: (cause) => toThreadTurnContextError('Failed to load thread workspace', cause),
54
+ }).pipe(Effect.withSpan('ThreadTurnContext.loadWorkspace'))
61
55
 
62
- const workspaceLifecycleState = yield* effectTryMaybeAsync(
63
- () => params.workspaceProvider?.getLifecycleState?.(workspace),
64
- 'Failed to load workspace lifecycle state',
65
- ).pipe(Effect.withSpan('ThreadTurnContext.loadWorkspaceLifecycleState'))
66
- const workspaceProfileState = yield* effectTryMaybeAsync(
67
- () => params.workspaceProvider?.readProfileProjectionState?.(workspace),
68
- 'Failed to load workspace profile state',
69
- ).pipe(Effect.withSpan('ThreadTurnContext.loadWorkspaceProfileState'))
56
+ const workspaceProvider = params.workspaceProvider
57
+ const getLifecycleState = workspaceProvider?.getLifecycleState
58
+ ? (() => {
59
+ const run = workspaceProvider.getLifecycleState.bind(workspaceProvider)
60
+ return (workspaceRecord: Record<string, unknown>) => run(workspaceRecord)
61
+ })()
62
+ : undefined
63
+ const workspaceLifecycleState = getLifecycleState
64
+ ? yield* Effect.tryPromise({
65
+ try: () => getLifecycleState(workspace),
66
+ catch: (cause) => toThreadTurnContextError('Failed to load workspace lifecycle state', cause),
67
+ }).pipe(Effect.withSpan('ThreadTurnContext.loadWorkspaceLifecycleState'))
68
+ : undefined
69
+ const readProfileProjectionState = workspaceProvider?.readProfileProjectionState
70
+ ? (() => {
71
+ const run = workspaceProvider.readProfileProjectionState.bind(workspaceProvider)
72
+ return (workspaceRecord: Record<string, unknown>) => run(workspaceRecord)
73
+ })()
74
+ : undefined
75
+ const workspaceProfileState = readProfileProjectionState
76
+ ? yield* Effect.tryPromise({
77
+ try: () => readProfileProjectionState(workspace),
78
+ catch: (cause) => toThreadTurnContextError('Failed to load workspace profile state', cause),
79
+ }).pipe(Effect.withSpan('ThreadTurnContext.loadWorkspaceProfileState'))
80
+ : undefined
70
81
 
71
82
  const onboardingActive = workspaceLifecycleState?.bootstrapActive ?? false
72
- const linearInstallation = yield* effectTryPromise(
73
- () => getLinearInstallationByOrgId(params.pluginRuntime, params.orgRef),
74
- 'Failed to load Linear installation',
75
- ).pipe(
83
+ const linearInstallation = yield* Effect.tryPromise({
84
+ try: () => getLinearInstallationByOrgId(params.pluginRuntime, params.orgRef),
85
+ catch: (cause) => toThreadTurnContextError('Failed to load Linear installation', cause),
86
+ }).pipe(
76
87
  Effect.catch(() => Effect.succeed(null)),
77
88
  Effect.withSpan('ThreadTurnContext.loadLinearInstallation'),
78
89
  )
79
- const githubInstallation = yield* effectTryPromise(
80
- () => getGithubInstallationForOrganization(params.pluginRuntime, params.orgIdString),
81
- 'Failed to load GitHub installation',
82
- ).pipe(
90
+ const githubInstallation = yield* Effect.tryPromise({
91
+ try: () => getGithubInstallationForOrganization(params.pluginRuntime, params.orgIdString),
92
+ catch: (cause) => toThreadTurnContextError('Failed to load GitHub installation', cause),
93
+ }).pipe(
83
94
  Effect.catch(() => Effect.succeed(null)),
84
95
  Effect.withSpan('ThreadTurnContext.loadGithubInstallation'),
85
96
  )
86
- const indexedRepoContext = yield* effectTryPromise(
87
- () => buildIndexedRepositoriesContext(params.runtimeAdapters, params.orgIdString),
88
- 'Failed to build indexed repository context',
89
- ).pipe(
97
+ const indexedRepoContext = yield* Effect.tryPromise({
98
+ try: () => buildIndexedRepositoriesContext(params.runtimeAdapters, params.orgIdString),
99
+ catch: (cause) => toThreadTurnContextError('Failed to build indexed repository context', cause),
100
+ }).pipe(
90
101
  Effect.catch(() =>
91
102
  Effect.succeed({
92
103
  provideRepoTool: false,
@@ -96,17 +107,31 @@ export const assembleThreadTurnContext = Effect.fn('ThreadTurnContext.assemble')
96
107
  ),
97
108
  Effect.withSpan('ThreadTurnContext.buildIndexedRepositoriesContext'),
98
109
  )
99
- const recentDomainEvents = yield* effectTryMaybeAsync(
100
- () => params.workspaceProvider?.listRecentDomainEvents?.(params.orgRef, 5) ?? [],
101
- 'Failed to load recent domain events',
102
- ).pipe(Effect.withSpan('ThreadTurnContext.loadRecentDomainEvents'))
110
+ const listRecentDomainEvents = workspaceProvider?.listRecentDomainEvents
111
+ ? (() => {
112
+ const run = workspaceProvider.listRecentDomainEvents.bind(workspaceProvider)
113
+ return (workspaceId: RecordIdRef, limit?: number) => run(workspaceId, limit)
114
+ })()
115
+ : undefined
116
+ const recentDomainEvents = listRecentDomainEvents
117
+ ? yield* Effect.tryPromise({
118
+ try: () => listRecentDomainEvents(params.orgRef, 5),
119
+ catch: (cause) => toThreadTurnContextError('Failed to load recent domain events', cause),
120
+ }).pipe(Effect.withSpan('ThreadTurnContext.loadRecentDomainEvents'))
121
+ : []
122
+ const buildPromptSummary = workspaceProvider?.buildPromptSummary
123
+ ? (() => {
124
+ const run = workspaceProvider.buildPromptSummary.bind(workspaceProvider)
125
+ return (workspaceId: RecordIdRef) => run(workspaceId)
126
+ })()
127
+ : undefined
103
128
  const promptSummary =
104
- params.workspaceProvider?.buildPromptSummary === undefined
129
+ buildPromptSummary === undefined
105
130
  ? undefined
106
- : yield* effectTryMaybeAsync(
107
- () => params.workspaceProvider?.buildPromptSummary?.(params.orgRef),
108
- 'Failed to build workspace prompt summary',
109
- ).pipe(
131
+ : yield* Effect.tryPromise({
132
+ try: () => buildPromptSummary(params.orgRef),
133
+ catch: (cause) => toThreadTurnContextError('Failed to build workspace prompt summary', cause),
134
+ }).pipe(
110
135
  Effect.catch(() => Effect.as(Effect.void, undefined as string | undefined)),
111
136
  Effect.withSpan('ThreadTurnContext.buildPromptSummary'),
112
137
  )
@@ -120,41 +145,53 @@ export const assembleThreadTurnContext = Effect.fn('ThreadTurnContext.assemble')
120
145
  userName: params.userName ?? undefined,
121
146
  recentDomainEvents,
122
147
  })
148
+ const buildRetrievedKnowledgeSection = workspaceProvider?.buildRetrievedKnowledgeSection
149
+ ? (() => {
150
+ const run = workspaceProvider.buildRetrievedKnowledgeSection.bind(workspaceProvider)
151
+ return (input: Parameters<NonNullable<LotaRuntimeWorkspaceProvider['buildRetrievedKnowledgeSection']>>[0]) =>
152
+ run(input)
153
+ })()
154
+ : undefined
123
155
  const initialRetrievedKnowledgeSection: string | undefined = !params.messageText
124
156
  ? undefined
125
- : yield* effectTryMaybeAsync(
126
- () =>
127
- params.workspaceProvider?.buildRetrievedKnowledgeSection?.({
128
- workspaceId: params.orgIdString,
129
- userId: params.userIdString,
130
- query: params.messageText,
131
- }),
132
- 'Failed to build retrieved knowledge section',
133
- ).pipe(Effect.withSpan('ThreadTurnContext.buildRetrievedKnowledgeSection'))
157
+ : buildRetrievedKnowledgeSection
158
+ ? yield* Effect.tryPromise({
159
+ try: () =>
160
+ buildRetrievedKnowledgeSection({
161
+ workspaceId: params.orgIdString,
162
+ userId: params.userIdString,
163
+ query: params.messageText,
164
+ }),
165
+ catch: (cause) => toThreadTurnContextError('Failed to build retrieved knowledge section', cause),
166
+ }).pipe(Effect.withSpan('ThreadTurnContext.buildRetrievedKnowledgeSection'))
167
+ : undefined
134
168
 
135
- const buildContextResultValue = yield* effectTryMaybeAsync(
136
- () =>
137
- params.turnHooks.buildContext?.({
138
- thread: params.thread,
139
- threadRef: params.threadRef,
140
- orgRef: params.orgRef,
141
- userRef: params.userRef,
142
- userName: params.userName,
143
- workspace,
144
- onboardingActive,
145
- messageText: params.messageText,
146
- linearInstalled: initialLinearInstalled,
147
- githubInstalled: initialGithubInstalled,
148
- indexedRepoContext,
149
- promptContext: initialPromptContext,
150
- workspaceLifecycleState,
151
- workspaceProfileState,
152
- promptSummary,
153
- recentDomainEvents,
154
- retrievedKnowledgeSection: initialRetrievedKnowledgeSection,
155
- }),
156
- 'Failed to build thread context',
157
- ).pipe(Effect.withSpan('ThreadTurnContext.buildContextHook'))
169
+ const buildContext = params.turnHooks.buildContext
170
+ const buildContextResultValue = buildContext
171
+ ? yield* Effect.tryPromise({
172
+ try: () =>
173
+ buildContext({
174
+ thread: params.thread,
175
+ threadRef: params.threadRef,
176
+ orgRef: params.orgRef,
177
+ userRef: params.userRef,
178
+ userName: params.userName,
179
+ workspace,
180
+ onboardingActive,
181
+ messageText: params.messageText,
182
+ linearInstalled: initialLinearInstalled,
183
+ githubInstalled: initialGithubInstalled,
184
+ indexedRepoContext,
185
+ promptContext: initialPromptContext,
186
+ workspaceLifecycleState,
187
+ workspaceProfileState,
188
+ promptSummary,
189
+ recentDomainEvents,
190
+ retrievedKnowledgeSection: initialRetrievedKnowledgeSection,
191
+ }),
192
+ catch: (cause) => toThreadTurnContextError('Failed to build thread context', cause),
193
+ }).pipe(Effect.withSpan('ThreadTurnContext.buildContextHook'))
194
+ : undefined
158
195
  const buildContextResult = isRecord(buildContextResultValue) ? buildContextResultValue : null
159
196
 
160
197
  const buildContextPromptDetails = readOptionalString(buildContextResult?.systemWorkspaceDetails)
@@ -171,31 +208,34 @@ export const assembleThreadTurnContext = Effect.fn('ThreadTurnContext.assemble')
171
208
  const githubInstalled =
172
209
  buildContextGithubInstalled !== undefined ? buildContextGithubInstalled : initialGithubInstalled
173
210
 
211
+ const buildExtraInstructionSections = params.turnHooks.buildExtraInstructionSections
174
212
  const hookInstructionSections = readInstructionSections(
175
- yield* effectTryMaybeAsync(
176
- () =>
177
- params.turnHooks.buildExtraInstructionSections?.({
178
- thread: params.thread,
179
- threadRef: params.threadRef,
180
- orgRef: params.orgRef,
181
- userRef: params.userRef,
182
- userName: params.userName,
183
- workspace,
184
- onboardingActive,
185
- messageText: params.messageText,
186
- linearInstalled,
187
- githubInstalled,
188
- indexedRepoContext,
189
- promptContext,
190
- workspaceLifecycleState,
191
- workspaceProfileState,
192
- promptSummary,
193
- recentDomainEvents,
194
- retrievedKnowledgeSection,
195
- context: buildContextResult,
196
- }),
197
- 'Failed to build extra instruction sections',
198
- ).pipe(Effect.withSpan('ThreadTurnContext.buildExtraInstructionSections')),
213
+ buildExtraInstructionSections
214
+ ? yield* Effect.tryPromise({
215
+ try: () =>
216
+ buildExtraInstructionSections({
217
+ thread: params.thread,
218
+ threadRef: params.threadRef,
219
+ orgRef: params.orgRef,
220
+ userRef: params.userRef,
221
+ userName: params.userName,
222
+ workspace,
223
+ onboardingActive,
224
+ messageText: params.messageText,
225
+ linearInstalled,
226
+ githubInstalled,
227
+ indexedRepoContext,
228
+ promptContext,
229
+ workspaceLifecycleState,
230
+ workspaceProfileState,
231
+ promptSummary,
232
+ recentDomainEvents,
233
+ retrievedKnowledgeSection,
234
+ context: buildContextResult,
235
+ }),
236
+ catch: (cause) => toThreadTurnContextError('Failed to build extra instruction sections', cause),
237
+ }).pipe(Effect.withSpan('ThreadTurnContext.buildExtraInstructionSections'))
238
+ : undefined,
199
239
  )
200
240
 
201
241
  return {
@@ -2,79 +2,48 @@ import type { ChatMessage } from '@lota-sdk/shared'
2
2
  import { Schema, Effect } from 'effect'
3
3
 
4
4
  import { serverLogger } from '../config/logger'
5
- import { effectTryMaybeAsync } from '../effect/helpers'
5
+ import { ERROR_TAGS } from '../effect/errors'
6
6
 
7
- export class TurnLifecycleError extends Schema.TaggedErrorClass<TurnLifecycleError>()('TurnLifecycleError', {
7
+ export class TurnLifecycleError extends Schema.TaggedErrorClass<TurnLifecycleError>()(ERROR_TAGS.TurnLifecycleError, {
8
8
  message: Schema.String,
9
9
  cause: Schema.optional(Schema.Defect),
10
10
  }) {}
11
11
 
12
- type MaybeAsync<A> = A | PromiseLike<A>
13
- type MaybeEffect<A> = MaybeAsync<A> | Effect.Effect<A, TurnLifecycleError>
14
-
15
- function effectFromMaybeEffect<A>(
16
- evaluate: () => MaybeEffect<A>,
17
- onError: (error: unknown) => TurnLifecycleError,
18
- ): Effect.Effect<A, TurnLifecycleError> {
19
- return Effect.suspend(() => {
20
- try {
21
- const result = evaluate()
22
- return Effect.isEffect(result)
23
- ? result.pipe(Effect.mapError(onError))
24
- : effectTryMaybeAsync(() => result, onError)
25
- } catch (error) {
26
- return Effect.fail(onError(error))
27
- }
28
- })
29
- }
30
-
31
12
  export function finalizeTurnRunEffect(params: {
32
13
  serverRunId: string
33
- getEntity: () => MaybeEffect<{ lastCompactedMessageId?: string | null; compactionSummary?: string | null }>
34
- getUncompactedMessages: (cursor?: string) => MaybeEffect<ChatMessage[]>
14
+ getEntity: () => Effect.Effect<
15
+ { lastCompactedMessageId?: string | null; compactionSummary?: string | null },
16
+ TurnLifecycleError
17
+ >
18
+ getUncompactedMessages: (cursor?: string) => Effect.Effect<ChatMessage[], TurnLifecycleError>
35
19
  assessCompaction: (summaryText: string, messages: ChatMessage[]) => { shouldCompact: boolean }
36
- enqueueCompaction: () => MaybeEffect<void>
20
+ enqueueCompaction: () => Effect.Effect<void, TurnLifecycleError>
37
21
  unregisterRun: (runId: string) => void
38
- clearActiveRunId: (runId: string) => MaybeEffect<void>
22
+ clearActiveRunId: (runId: string) => Effect.Effect<void, TurnLifecycleError>
39
23
  disposeAbort: () => void
40
24
  activeStreamId?: string
41
- clearActiveStreamId?: (streamId: string) => MaybeEffect<void>
25
+ clearActiveStreamId?: (streamId: string) => Effect.Effect<void, TurnLifecycleError>
42
26
  }): Effect.Effect<void, TurnLifecycleError> {
43
27
  return Effect.gen(function* () {
44
28
  // Clear the active run immediately so new messages are not blocked
45
29
  params.unregisterRun(params.serverRunId)
46
- yield* effectFromMaybeEffect(
47
- () => params.clearActiveRunId(params.serverRunId),
48
- (error) => new TurnLifecycleError({ message: String(error), cause: error }),
49
- )
30
+ yield* params.clearActiveRunId(params.serverRunId)
50
31
  const activeStreamId = params.activeStreamId
51
32
  const clearActiveStreamId = params.clearActiveStreamId
52
33
  if (activeStreamId && clearActiveStreamId) {
53
- yield* effectFromMaybeEffect(
54
- () => clearActiveStreamId(activeStreamId),
55
- (error) => new TurnLifecycleError({ message: String(error), cause: error }),
56
- )
34
+ yield* clearActiveStreamId(activeStreamId)
57
35
  }
58
36
  params.disposeAbort()
59
37
 
60
38
  yield* Effect.gen(function* () {
61
- const entity = yield* effectFromMaybeEffect(
62
- () => params.getEntity(),
63
- (error) => new TurnLifecycleError({ message: String(error), cause: error }),
64
- )
39
+ const entity = yield* params.getEntity()
65
40
  const cursor = typeof entity.lastCompactedMessageId === 'string' ? entity.lastCompactedMessageId : undefined
66
- const uncompactedMessages = yield* effectFromMaybeEffect(
67
- () => params.getUncompactedMessages(cursor),
68
- (error) => new TurnLifecycleError({ message: String(error), cause: error }),
69
- )
41
+ const uncompactedMessages = yield* params.getUncompactedMessages(cursor)
70
42
  const summaryText = typeof entity.compactionSummary === 'string' ? entity.compactionSummary : ''
71
43
  const { shouldCompact } = params.assessCompaction(summaryText, uncompactedMessages)
72
44
 
73
45
  if (shouldCompact) {
74
- yield* effectFromMaybeEffect(
75
- () => params.enqueueCompaction(),
76
- (error) => new TurnLifecycleError({ message: String(error), cause: error }),
77
- )
46
+ yield* params.enqueueCompaction()
78
47
  }
79
48
  }).pipe(
80
49
  Effect.catch((error: unknown) =>
@@ -43,7 +43,7 @@ type AgentActivityDeps = {
43
43
  }
44
44
 
45
45
  class AgentActivityServiceError extends Schema.TaggedErrorClass<AgentActivityServiceError>()(
46
- 'AgentActivityServiceError',
46
+ '@lota-sdk/core/AgentActivityServiceError',
47
47
  { message: Schema.String, cause: Schema.Defect },
48
48
  ) {}
49
49