@lota-sdk/core 0.4.8 → 0.4.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (272) hide show
  1. package/package.json +11 -12
  2. package/src/ai/embedding-cache.ts +96 -22
  3. package/src/ai-gateway/ai-gateway.ts +766 -223
  4. package/src/config/agent-defaults.ts +189 -75
  5. package/src/config/agent-types.ts +54 -4
  6. package/src/config/background-processing.ts +1 -1
  7. package/src/config/constants.ts +8 -2
  8. package/src/config/index.ts +0 -1
  9. package/src/config/logger.ts +299 -19
  10. package/src/config/thread-defaults.ts +40 -20
  11. package/src/create-runtime.ts +200 -449
  12. package/src/db/base.service.ts +52 -28
  13. package/src/db/cursor-pagination.ts +71 -30
  14. package/src/db/memory-query-builder.ts +2 -1
  15. package/src/db/memory-store.helpers.ts +4 -7
  16. package/src/db/memory-store.ts +868 -601
  17. package/src/db/memory.ts +396 -280
  18. package/src/db/record-id.ts +32 -10
  19. package/src/db/schema-fingerprint.ts +30 -12
  20. package/src/db/service-normalization.ts +288 -0
  21. package/src/db/service.ts +912 -779
  22. package/src/db/startup.ts +153 -68
  23. package/src/db/transaction-conflict.ts +15 -0
  24. package/src/effect/awaitable-effect.ts +96 -0
  25. package/src/effect/errors.ts +121 -0
  26. package/src/effect/helpers.ts +123 -0
  27. package/src/effect/index.ts +24 -0
  28. package/src/effect/layers.ts +238 -0
  29. package/src/effect/runtime-ref.ts +25 -0
  30. package/src/effect/runtime.ts +46 -0
  31. package/src/effect/services.ts +61 -0
  32. package/src/effect/zod.ts +43 -0
  33. package/src/embeddings/provider.ts +128 -83
  34. package/src/index.ts +48 -1
  35. package/src/openrouter/direct-provider.ts +11 -35
  36. package/src/queues/autonomous-job.queue.ts +117 -73
  37. package/src/queues/context-compaction.queue.ts +50 -17
  38. package/src/queues/delayed-node-promotion.queue.ts +46 -17
  39. package/src/queues/document-processor.queue.ts +52 -77
  40. package/src/queues/memory-consolidation.queue.ts +47 -32
  41. package/src/queues/organization-learning.queue.ts +26 -4
  42. package/src/queues/plan-agent-heartbeat.queue.ts +71 -24
  43. package/src/queues/plan-scheduler.queue.ts +97 -33
  44. package/src/queues/post-chat-memory.queue.ts +56 -26
  45. package/src/queues/queue-factory.ts +227 -59
  46. package/src/queues/standalone-worker.ts +39 -0
  47. package/src/queues/title-generation.queue.ts +45 -11
  48. package/src/redis/connection.ts +182 -113
  49. package/src/redis/index.ts +6 -8
  50. package/src/redis/org-memory-lock.ts +60 -27
  51. package/src/redis/redis-lease-lock.ts +200 -121
  52. package/src/redis/runtime-connection.ts +20 -0
  53. package/src/redis/stream-context.ts +92 -46
  54. package/src/runtime/agent-identity-overrides.ts +2 -2
  55. package/src/runtime/agent-runtime-policy.ts +5 -2
  56. package/src/runtime/agent-stream-helpers.ts +24 -9
  57. package/src/runtime/chat-run-orchestration.ts +102 -19
  58. package/src/runtime/chat-run-registry.ts +36 -2
  59. package/src/runtime/context-compaction/context-compaction-runtime.ts +107 -0
  60. package/src/runtime/{context-compaction.ts → context-compaction/context-compaction.ts} +161 -94
  61. package/src/runtime/domain-layer.ts +192 -0
  62. package/src/runtime/execution-plan-visibility.ts +2 -2
  63. package/src/runtime/execution-plan.ts +42 -15
  64. package/src/runtime/graph-designer.ts +16 -4
  65. package/src/runtime/helper-model.ts +139 -48
  66. package/src/runtime/index.ts +7 -8
  67. package/src/runtime/indexed-repositories-policy.ts +3 -3
  68. package/src/runtime/{memory-block.ts → memory/memory-block.ts} +50 -36
  69. package/src/runtime/{memory-digest-policy.ts → memory/memory-digest-policy.ts} +1 -1
  70. package/src/runtime/{memory-pipeline.ts → memory/memory-pipeline.ts} +54 -67
  71. package/src/runtime/{memory-prompts-fact.ts → memory/memory-prompts-fact.ts} +2 -2
  72. package/src/runtime/memory/memory-scope.ts +53 -0
  73. package/src/runtime/plugin-resolution.ts +124 -25
  74. package/src/runtime/plugin-types.ts +9 -1
  75. package/src/runtime/post-turn-side-effects.ts +177 -130
  76. package/src/runtime/retrieval-adapters.ts +40 -6
  77. package/src/runtime/runtime-accessors.ts +92 -0
  78. package/src/runtime/runtime-config.ts +150 -61
  79. package/src/runtime/runtime-extensions.ts +23 -25
  80. package/src/runtime/runtime-lifecycle.ts +124 -0
  81. package/src/runtime/runtime-services.ts +386 -0
  82. package/src/runtime/runtime-token.ts +47 -0
  83. package/src/runtime/social-chat/social-chat-agent-runner.ts +159 -0
  84. package/src/runtime/{social-chat-history.ts → social-chat/social-chat-history.ts} +51 -20
  85. package/src/runtime/social-chat/social-chat.ts +630 -0
  86. package/src/runtime/specialist-runner.ts +36 -10
  87. package/src/runtime/team-consultation/team-consultation-orchestrator.ts +433 -0
  88. package/src/runtime/{team-consultation-prompts.ts → team-consultation/team-consultation-prompts.ts} +6 -2
  89. package/src/runtime/thread-chat-helpers.ts +2 -2
  90. package/src/runtime/thread-plan-turn.ts +2 -1
  91. package/src/runtime/thread-turn-context.ts +183 -111
  92. package/src/runtime/turn-lifecycle.ts +93 -27
  93. package/src/services/agent-activity.service.ts +287 -203
  94. package/src/services/agent-executor.service.ts +253 -149
  95. package/src/services/artifact.service.ts +231 -149
  96. package/src/services/attachment.service.ts +171 -115
  97. package/src/services/autonomous-job.service.ts +890 -491
  98. package/src/services/background-work.service.ts +54 -0
  99. package/src/services/chat-run-registry.service.ts +13 -1
  100. package/src/services/context-compaction.service.ts +136 -86
  101. package/src/services/document-chunk.service.ts +151 -88
  102. package/src/services/execution-plan/execution-plan-approval.ts +26 -0
  103. package/src/services/execution-plan/execution-plan-context.ts +29 -0
  104. package/src/services/execution-plan/execution-plan-graph.ts +278 -0
  105. package/src/services/execution-plan/execution-plan-schedule.ts +84 -0
  106. package/src/services/execution-plan/execution-plan-spec.ts +75 -0
  107. package/src/services/execution-plan/execution-plan.service.ts +1041 -0
  108. package/src/services/feedback-loop.service.ts +132 -76
  109. package/src/services/global-orchestrator.service.ts +101 -168
  110. package/src/services/graph-full-routing.ts +193 -0
  111. package/src/services/index.ts +19 -21
  112. package/src/services/institutional-memory.service.ts +213 -125
  113. package/src/services/learned-skill.service.ts +368 -260
  114. package/src/services/memory/memory-conversation.ts +95 -0
  115. package/src/services/memory/memory-errors.ts +27 -0
  116. package/src/services/memory/memory-org-memory.ts +50 -0
  117. package/src/services/memory/memory-preseeded.ts +86 -0
  118. package/src/services/memory/memory-rerank.ts +297 -0
  119. package/src/services/{memory-utils.ts → memory/memory-utils.ts} +6 -5
  120. package/src/services/memory/memory.service.ts +674 -0
  121. package/src/services/memory/rerank.service.ts +201 -0
  122. package/src/services/monitoring-window.service.ts +92 -70
  123. package/src/services/mutating-approval.service.ts +62 -53
  124. package/src/services/node-workspace.service.ts +141 -98
  125. package/src/services/notification.service.ts +29 -16
  126. package/src/services/organization-member.service.ts +120 -66
  127. package/src/services/organization.service.ts +153 -77
  128. package/src/services/ownership-dispatcher.service.ts +456 -263
  129. package/src/services/plan/plan-agent-heartbeat.service.ts +234 -0
  130. package/src/services/plan/plan-agent-query.service.ts +322 -0
  131. package/src/services/{plan-approval.service.ts → plan/plan-approval.service.ts} +45 -22
  132. package/src/services/plan/plan-artifact.service.ts +60 -0
  133. package/src/services/plan/plan-builder.service.ts +76 -0
  134. package/src/services/plan/plan-checkpoint.service.ts +103 -0
  135. package/src/services/{plan-compiler.service.ts → plan/plan-compiler.service.ts} +26 -9
  136. package/src/services/plan/plan-completion-side-effects.ts +169 -0
  137. package/src/services/plan/plan-coordination.service.ts +181 -0
  138. package/src/services/plan/plan-cycle.service.ts +405 -0
  139. package/src/services/plan/plan-deadline.service.ts +533 -0
  140. package/src/services/plan/plan-event-delivery.service.ts +266 -0
  141. package/src/services/plan/plan-executor-context.ts +35 -0
  142. package/src/services/plan/plan-executor-graph.ts +522 -0
  143. package/src/services/plan/plan-executor-helpers.ts +307 -0
  144. package/src/services/plan/plan-executor-persistence.ts +209 -0
  145. package/src/services/plan/plan-executor.service.ts +1737 -0
  146. package/src/services/{plan-helpers.ts → plan/plan-helpers.ts} +1 -1
  147. package/src/services/{plan-run-data.ts → plan/plan-run-data.ts} +4 -4
  148. package/src/services/plan/plan-run-serialization.ts +15 -0
  149. package/src/services/plan/plan-run.service.ts +637 -0
  150. package/src/services/plan/plan-scheduler.service.ts +379 -0
  151. package/src/services/plan/plan-template.service.ts +224 -0
  152. package/src/services/plan/plan-transaction-events.ts +36 -0
  153. package/src/services/plan/plan-validator.service.ts +907 -0
  154. package/src/services/plan/plan-workspace.service.ts +131 -0
  155. package/src/services/plugin-executor.service.ts +102 -68
  156. package/src/services/quality-metrics.service.ts +112 -94
  157. package/src/services/queue-job.service.ts +288 -231
  158. package/src/services/recent-activity-title.service.ts +73 -36
  159. package/src/services/recent-activity.service.ts +274 -259
  160. package/src/services/skill-resolver.service.ts +38 -12
  161. package/src/services/social-chat-history.service.ts +190 -122
  162. package/src/services/system-executor.service.ts +96 -61
  163. package/src/services/thread/thread-active-run.ts +203 -0
  164. package/src/services/thread/thread-bootstrap.ts +385 -0
  165. package/src/services/thread/thread-listing.ts +199 -0
  166. package/src/services/thread/thread-memory-block.ts +130 -0
  167. package/src/services/thread/thread-message.service.ts +379 -0
  168. package/src/services/thread/thread-record-store.ts +155 -0
  169. package/src/services/thread/thread-title.service.ts +74 -0
  170. package/src/services/thread/thread-turn-execution.ts +280 -0
  171. package/src/services/thread/thread-turn-message-context.ts +73 -0
  172. package/src/services/thread/thread-turn-preparation.service.ts +1148 -0
  173. package/src/services/thread/thread-turn-streaming.ts +403 -0
  174. package/src/services/thread/thread-turn-tracing.ts +35 -0
  175. package/src/services/thread/thread-turn.ts +376 -0
  176. package/src/services/thread/thread.service.ts +344 -0
  177. package/src/services/user.service.ts +82 -32
  178. package/src/services/write-intent-validator.service.ts +63 -51
  179. package/src/storage/attachment-parser.ts +69 -27
  180. package/src/storage/attachment-storage.service.ts +334 -275
  181. package/src/storage/generated-document-storage.service.ts +66 -34
  182. package/src/system-agents/agent-result.ts +3 -1
  183. package/src/system-agents/context-compaction.agent.ts +3 -3
  184. package/src/system-agents/delegated-agent-factory.ts +159 -90
  185. package/src/system-agents/helper-agent-options.ts +1 -1
  186. package/src/system-agents/memory-reranker.agent.ts +3 -3
  187. package/src/system-agents/memory.agent.ts +3 -3
  188. package/src/system-agents/recent-activity-title-refiner.agent.ts +3 -3
  189. package/src/system-agents/regular-chat-memory-digest.agent.ts +3 -3
  190. package/src/system-agents/skill-extractor.agent.ts +3 -3
  191. package/src/system-agents/skill-manager.agent.ts +3 -3
  192. package/src/system-agents/thread-router.agent.ts +157 -113
  193. package/src/system-agents/title-generator.agent.ts +3 -3
  194. package/src/tools/execution-plan.tool.ts +241 -171
  195. package/src/tools/fetch-webpage.tool.ts +29 -18
  196. package/src/tools/firecrawl-client.ts +26 -6
  197. package/src/tools/index.ts +1 -0
  198. package/src/tools/memory-block.tool.ts +14 -6
  199. package/src/tools/plan-approval.tool.ts +57 -47
  200. package/src/tools/read-file-parts.tool.ts +44 -33
  201. package/src/tools/remember-memory.tool.ts +65 -45
  202. package/src/tools/search-web.tool.ts +33 -22
  203. package/src/tools/search.tool.ts +41 -29
  204. package/src/tools/team-think.tool.ts +125 -84
  205. package/src/tools/user-questions.tool.ts +4 -3
  206. package/src/tools/web-tool-shared.ts +6 -0
  207. package/src/utils/async.ts +25 -22
  208. package/src/utils/crypto.ts +21 -0
  209. package/src/utils/date-time.ts +40 -1
  210. package/src/utils/errors.ts +111 -20
  211. package/src/utils/hono-error-handler.ts +24 -39
  212. package/src/utils/index.ts +2 -1
  213. package/src/utils/null-proto-record.ts +41 -0
  214. package/src/utils/sse-keepalive.ts +124 -21
  215. package/src/workers/bootstrap.ts +164 -52
  216. package/src/workers/memory-consolidation.worker.ts +325 -237
  217. package/src/workers/organization-learning.worker.ts +50 -16
  218. package/src/workers/regular-chat-memory-digest.helpers.ts +28 -27
  219. package/src/workers/regular-chat-memory-digest.runner.ts +185 -114
  220. package/src/workers/skill-extraction.runner.ts +176 -93
  221. package/src/workers/utils/file-section-chunker.ts +8 -10
  222. package/src/workers/utils/repo-structure-extractor.ts +349 -260
  223. package/src/workers/utils/repomix-file-sections.ts +2 -2
  224. package/src/workers/utils/thread-message-query.ts +97 -38
  225. package/src/workers/worker-utils.ts +74 -31
  226. package/src/config/debug-logger.ts +0 -47
  227. package/src/config/search.ts +0 -3
  228. package/src/redis/connection-accessor.ts +0 -26
  229. package/src/runtime/agent-types.ts +0 -1
  230. package/src/runtime/context-compaction-runtime.ts +0 -87
  231. package/src/runtime/memory-scope.ts +0 -43
  232. package/src/runtime/social-chat-agent-runner.ts +0 -118
  233. package/src/runtime/social-chat.ts +0 -516
  234. package/src/runtime/team-consultation-orchestrator.ts +0 -272
  235. package/src/services/adaptive-playbook.service.ts +0 -152
  236. package/src/services/artifact-provenance.service.ts +0 -172
  237. package/src/services/chat-attachments.service.ts +0 -17
  238. package/src/services/context-compaction-runtime.singleton.ts +0 -13
  239. package/src/services/execution-plan.service.ts +0 -1118
  240. package/src/services/memory.service.ts +0 -914
  241. package/src/services/plan-agent-heartbeat.service.ts +0 -136
  242. package/src/services/plan-agent-query.service.ts +0 -267
  243. package/src/services/plan-artifact.service.ts +0 -50
  244. package/src/services/plan-builder.service.ts +0 -67
  245. package/src/services/plan-checkpoint.service.ts +0 -81
  246. package/src/services/plan-completion-side-effects.ts +0 -80
  247. package/src/services/plan-coordination.service.ts +0 -157
  248. package/src/services/plan-cycle.service.ts +0 -284
  249. package/src/services/plan-deadline.service.ts +0 -430
  250. package/src/services/plan-event-delivery.service.ts +0 -166
  251. package/src/services/plan-executor.service.ts +0 -1950
  252. package/src/services/plan-run.service.ts +0 -515
  253. package/src/services/plan-scheduler.service.ts +0 -240
  254. package/src/services/plan-template.service.ts +0 -177
  255. package/src/services/plan-validator.service.ts +0 -818
  256. package/src/services/plan-workspace.service.ts +0 -83
  257. package/src/services/rerank.service.ts +0 -156
  258. package/src/services/thread-message.service.ts +0 -275
  259. package/src/services/thread-plan-registry.service.ts +0 -22
  260. package/src/services/thread-title.service.ts +0 -39
  261. package/src/services/thread-turn-preparation.service.ts +0 -1147
  262. package/src/services/thread-turn.ts +0 -172
  263. package/src/services/thread.service.ts +0 -869
  264. package/src/utils/env.ts +0 -8
  265. /package/src/runtime/{context-compaction-constants.ts → context-compaction/context-compaction-constants.ts} +0 -0
  266. /package/src/runtime/{memory-format.ts → memory/memory-format.ts} +0 -0
  267. /package/src/runtime/{memory-prompts-parse.ts → memory/memory-prompts-parse.ts} +0 -0
  268. /package/src/runtime/{memory-prompts-update.ts → memory/memory-prompts-update.ts} +0 -0
  269. /package/src/runtime/{social-chat-prompts.ts → social-chat/social-chat-prompts.ts} +0 -0
  270. /package/src/services/{plan-node-spec.ts → plan/plan-node-spec.ts} +0 -0
  271. /package/src/services/{thread-constants.ts → thread/thread-constants.ts} +0 -0
  272. /package/src/services/{thread.types.ts → thread/thread.types.ts} +0 -0
@@ -0,0 +1,199 @@
1
+ import { THREAD } from '@lota-sdk/shared'
2
+ import { Schema, Effect } from 'effect'
3
+ import { BoundQuery } from 'surrealdb'
4
+
5
+ import type { RecordIdRef } from '../../db/record-id'
6
+ import type { SurrealDBService } from '../../db/service'
7
+ import { TABLES } from '../../db/tables'
8
+ import type { BadRequestError, ServiceError } from '../../effect/errors'
9
+ import { makeEffectTryPromiseWithMessage } from '../../effect/helpers'
10
+ import { ThreadSchema } from './thread.types'
11
+ import type { NormalizedThread, ThreadRecord } from './thread.types'
12
+
13
+ function buildListThreadsQuery(options: {
14
+ includeArchived: boolean
15
+ paginate: boolean
16
+ type?: string
17
+ types?: string[]
18
+ }): string {
19
+ const clauses = [`SELECT * FROM ${TABLES.THREAD}`, 'WHERE userId = $userId', ' AND organizationId = $orgId']
20
+
21
+ if (options.types) {
22
+ clauses.push(' AND type IN $types')
23
+ } else if (options.type) {
24
+ clauses.push(' AND type = $type')
25
+ }
26
+
27
+ if (!options.includeArchived) {
28
+ clauses.push(' AND status = "active"')
29
+ }
30
+ clauses.push('ORDER BY updatedAt DESC')
31
+ if (options.paginate) {
32
+ clauses.push('LIMIT $limit START $offset')
33
+ }
34
+ return clauses.join('\n')
35
+ }
36
+
37
+ export function createThreadListingHelpers(deps: {
38
+ db: SurrealDBService
39
+ normalizeThreads(
40
+ threads: ThreadRecord[],
41
+ options?: { checkLease?: boolean },
42
+ ): Effect.Effect<NormalizedThread[], BadRequestError | ServiceError>
43
+ }) {
44
+ class ThreadListingError extends Schema.TaggedErrorClass<ThreadListingError>()('ThreadListingError', {
45
+ message: Schema.String,
46
+ cause: Schema.optional(Schema.Defect),
47
+ }) {}
48
+
49
+ const effectTryPromise = makeEffectTryPromiseWithMessage(
50
+ (message, cause) => new ThreadListingError({ message, cause }),
51
+ )
52
+
53
+ function listThreads(
54
+ userId: RecordIdRef,
55
+ orgId: RecordIdRef,
56
+ options: { type?: string; types?: string[]; take?: number; page?: number; includeArchived?: boolean },
57
+ ): Effect.Effect<{ threads: NormalizedThread[]; hasMore: boolean }, ThreadListingError> {
58
+ const includeArchived = options.includeArchived ?? false
59
+ const type = options.type
60
+ const types = options.types
61
+
62
+ if (type === 'default' || type === 'thread') {
63
+ const vars: Record<string, unknown> = { userId, orgId, type }
64
+ return Effect.gen(function* () {
65
+ const threads = yield* effectTryPromise(
66
+ () =>
67
+ deps.db.queryMany(
68
+ new BoundQuery(buildListThreadsQuery({ includeArchived, paginate: false, type }), vars),
69
+ ThreadSchema,
70
+ ),
71
+ 'Failed to list threads.',
72
+ )
73
+ const normalizedThreads = yield* effectTryPromise(
74
+ () => deps.normalizeThreads(threads, { checkLease: false }),
75
+ 'Failed to normalize listed threads.',
76
+ )
77
+ return { threads: normalizedThreads, hasMore: false }
78
+ })
79
+ }
80
+
81
+ const take = options.take ?? THREAD.DEFAULT_PAGE_LIMIT
82
+ const page = options.page ?? 1
83
+ const vars: Record<string, unknown> = { userId, orgId, limit: take + 1, offset: (page - 1) * take }
84
+
85
+ if (types) {
86
+ vars.types = types
87
+ } else if (type) {
88
+ vars.type = type
89
+ }
90
+
91
+ return Effect.gen(function* () {
92
+ const threads = yield* effectTryPromise(
93
+ () =>
94
+ deps.db.queryMany(
95
+ new BoundQuery(buildListThreadsQuery({ includeArchived, paginate: true, type, types }), vars),
96
+ ThreadSchema,
97
+ ),
98
+ 'Failed to list paginated threads.',
99
+ )
100
+ const hasMore = threads.length > take
101
+ const sliced = hasMore ? threads.slice(0, take) : threads
102
+ const normalizedThreads = yield* effectTryPromise(
103
+ () => deps.normalizeThreads(sliced, { checkLease: false }),
104
+ 'Failed to normalize paginated threads.',
105
+ )
106
+ return { threads: normalizedThreads, hasMore }
107
+ })
108
+ }
109
+
110
+ function listOrganizationThreads(params: {
111
+ orgId: RecordIdRef
112
+ type?: string
113
+ agentId?: string
114
+ includeArchived?: boolean
115
+ }): Effect.Effect<NormalizedThread[], ThreadListingError> {
116
+ const whereClauses = ['organizationId = $orgId']
117
+ const variables: Record<string, unknown> = { orgId: params.orgId }
118
+
119
+ if (params.type) {
120
+ whereClauses.push('type = $type')
121
+ variables.type = params.type
122
+ }
123
+
124
+ if (params.agentId) {
125
+ whereClauses.push('agentId = $agentId')
126
+ variables.agentId = params.agentId
127
+ }
128
+
129
+ if (params.includeArchived !== true) {
130
+ whereClauses.push('status = "active"')
131
+ }
132
+
133
+ return Effect.gen(function* () {
134
+ const threads = yield* effectTryPromise(
135
+ () =>
136
+ deps.db.queryMany(
137
+ new BoundQuery(
138
+ `SELECT * FROM ${TABLES.THREAD}
139
+ WHERE ${whereClauses.join('\n AND ')}
140
+ ORDER BY createdAt ASC, id ASC`,
141
+ variables,
142
+ ),
143
+ ThreadSchema,
144
+ ),
145
+ 'Failed to list organization threads.',
146
+ )
147
+ return yield* effectTryPromise(
148
+ () => deps.normalizeThreads(threads, { checkLease: false }),
149
+ 'Failed to normalize organization threads.',
150
+ )
151
+ })
152
+ }
153
+
154
+ function listRecentThreads({
155
+ userId,
156
+ orgId,
157
+ excludeThreadId,
158
+ limit,
159
+ }: {
160
+ userId: RecordIdRef
161
+ orgId: RecordIdRef
162
+ excludeThreadId?: RecordIdRef
163
+ limit: number
164
+ }): Effect.Effect<NormalizedThread[], ThreadListingError> {
165
+ let excludeCondition = ''
166
+ const vars: Record<string, unknown> = { userId, orgId, limit }
167
+
168
+ if (excludeThreadId) {
169
+ excludeCondition = 'AND id != $excludeThreadId'
170
+ vars.excludeThreadId = excludeThreadId
171
+ }
172
+
173
+ return Effect.gen(function* () {
174
+ const threads = yield* effectTryPromise(
175
+ () =>
176
+ deps.db.queryMany(
177
+ new BoundQuery(
178
+ `SELECT * FROM ${TABLES.THREAD}
179
+ WHERE userId = $userId
180
+ AND organizationId = $orgId
181
+ ${excludeCondition}
182
+ AND status != "archived"
183
+ ORDER BY updatedAt DESC
184
+ LIMIT $limit`,
185
+ vars,
186
+ ),
187
+ ThreadSchema,
188
+ ),
189
+ 'Failed to list recent threads.',
190
+ )
191
+ return yield* effectTryPromise(
192
+ () => deps.normalizeThreads(threads, { checkLease: false }),
193
+ 'Failed to normalize recent threads.',
194
+ )
195
+ })
196
+ }
197
+
198
+ return { listThreads, listOrganizationThreads, listRecentThreads }
199
+ }
@@ -0,0 +1,130 @@
1
+ import type { Context } from 'effect'
2
+ import { Schema, Effect } from 'effect'
3
+
4
+ import { serverLogger } from '../../config/logger'
5
+ import type { RecordIdRef } from '../../db/record-id'
6
+ import { ensureRecordId, recordIdToString } from '../../db/record-id'
7
+ import { TABLES } from '../../db/tables'
8
+ import { makeEffectTryPromiseWithMessage } from '../../effect/helpers'
9
+ import {
10
+ appendToMemoryBlock,
11
+ compactMemoryBlockEntries,
12
+ formatPersistedMemoryBlockForPrompt,
13
+ MemoryBlockCompactError,
14
+ parseMemoryBlock,
15
+ serializeMemoryBlock,
16
+ } from '../../runtime/memory/memory-block'
17
+ import type { BackgroundWorkService } from '../background-work.service'
18
+ import type { makeContextCompactionService } from '../context-compaction.service'
19
+ import { MEMORY_BLOCK_COMPACTION_CHUNK_ENTRIES, MEMORY_BLOCK_COMPACTION_TRIGGER_ENTRIES } from './thread-constants'
20
+ import type { ThreadRecordStore } from './thread-record-store'
21
+ import type { ThreadRecord } from './thread.types'
22
+
23
+ type ContextCompactionServiceLike = Pick<ReturnType<typeof makeContextCompactionService>, 'compactMemoryBlock'>
24
+
25
+ type BackgroundWorker = Context.Service.Shape<typeof BackgroundWorkService>
26
+
27
+ class ThreadMemoryBlockError extends Schema.TaggedErrorClass<ThreadMemoryBlockError>()('ThreadMemoryBlockError', {
28
+ message: Schema.String,
29
+ cause: Schema.optional(Schema.Defect),
30
+ }) {}
31
+
32
+ const tryThreadMemoryBlockEffect = makeEffectTryPromiseWithMessage(
33
+ (message, cause) => new ThreadMemoryBlockError({ message, cause }),
34
+ )
35
+
36
+ export function formatMemoryBlockForPrompt(thread: Pick<ThreadRecord, 'memoryBlock' | 'memoryBlockSummary'>): string {
37
+ return formatPersistedMemoryBlockForPrompt({
38
+ summary: thread.memoryBlockSummary,
39
+ entries: parseMemoryBlock(thread.memoryBlock),
40
+ })
41
+ }
42
+
43
+ export function createThreadMemoryBlockHelpers(deps: {
44
+ threadStore: ThreadRecordStore
45
+ contextCompactionService: ContextCompactionServiceLike
46
+ background: BackgroundWorker
47
+ }) {
48
+ function appendMemoryBlock(threadId: RecordIdRef, entry: string): Effect.Effect<string, ThreadMemoryBlockError> {
49
+ return Effect.gen(function* () {
50
+ const threadRef = ensureRecordId(threadId, TABLES.THREAD)
51
+ const threadIdString = recordIdToString(threadRef, TABLES.THREAD)
52
+ const thread = yield* tryThreadMemoryBlockEffect(
53
+ () => deps.threadStore.getById(threadRef),
54
+ `Failed to load thread ${threadIdString} for memory block append`,
55
+ )
56
+ const entries = parseMemoryBlock(thread.memoryBlock)
57
+
58
+ const labelMatch = entry.match(/^(\w+):\s*/i)
59
+ const role = labelMatch ? labelMatch[1].toLowerCase() : 'system'
60
+ const content = labelMatch ? entry.slice(labelMatch[0].length).trim() : entry.trim()
61
+
62
+ const updatedEntries = appendToMemoryBlock(entries, role, content)
63
+ const serialized = serializeMemoryBlock(updatedEntries)
64
+
65
+ yield* tryThreadMemoryBlockEffect(
66
+ () => deps.threadStore.update(threadRef, { memoryBlock: serialized }),
67
+ `Failed to persist memory block for thread ${threadIdString}`,
68
+ )
69
+
70
+ if (updatedEntries.length >= MEMORY_BLOCK_COMPACTION_TRIGGER_ENTRIES) {
71
+ yield* deps.background.run(
72
+ compactMemoryBlock(threadRef).pipe(
73
+ Effect.catch((error: unknown) =>
74
+ Effect.sync(() => {
75
+ serverLogger.warn`Memory block compaction failed for ${threadIdString}: ${error}`
76
+ }),
77
+ ),
78
+ ),
79
+ 'thread-memory-block.compactMemoryBlock',
80
+ )
81
+ }
82
+
83
+ return formatMemoryBlockForPrompt({ memoryBlock: serialized, memoryBlockSummary: thread.memoryBlockSummary })
84
+ })
85
+ }
86
+
87
+ function compactMemoryBlock(threadId: RecordIdRef): Effect.Effect<boolean, ThreadMemoryBlockError> {
88
+ return Effect.gen(function* () {
89
+ const threadRef = ensureRecordId(threadId, TABLES.THREAD)
90
+ const threadIdString = recordIdToString(threadRef, TABLES.THREAD)
91
+ const thread = yield* tryThreadMemoryBlockEffect(
92
+ () => deps.threadStore.getById(threadRef),
93
+ `Failed to load thread ${threadIdString} for memory block compaction`,
94
+ )
95
+ const result = yield* tryThreadMemoryBlockEffect(
96
+ () =>
97
+ compactMemoryBlockEntries({
98
+ previousSummary: thread.memoryBlockSummary,
99
+ entries: parseMemoryBlock(thread.memoryBlock),
100
+ triggerEntries: MEMORY_BLOCK_COMPACTION_TRIGGER_ENTRIES,
101
+ chunkEntries: MEMORY_BLOCK_COMPACTION_CHUNK_ENTRIES,
102
+ compact: (params) =>
103
+ deps.contextCompactionService
104
+ .compactMemoryBlock(params)
105
+ .pipe(
106
+ Effect.mapError(
107
+ (cause) => new MemoryBlockCompactError({ message: 'compact callback failed', cause }),
108
+ ),
109
+ ),
110
+ }),
111
+ `Failed to compact memory block for thread ${threadIdString}`,
112
+ )
113
+
114
+ if (!result.compacted) return false
115
+
116
+ yield* tryThreadMemoryBlockEffect(
117
+ () =>
118
+ deps.threadStore.update(threadRef, {
119
+ memoryBlockSummary: result.summary || '',
120
+ memoryBlock: serializeMemoryBlock(result.entries),
121
+ }),
122
+ `Failed to persist compacted memory block for thread ${threadIdString}`,
123
+ )
124
+
125
+ return true
126
+ })
127
+ }
128
+
129
+ return { appendMemoryBlock, compactMemoryBlock }
130
+ }