@lota-sdk/core 0.1.11 → 0.1.12
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.
- package/package.json +2 -87
- package/src/ai/index.ts +3 -0
- package/src/bifrost/index.ts +1 -0
- package/src/config/agent-defaults.ts +30 -7
- package/src/config/constants.ts +0 -9
- package/src/config/debug-logger.ts +43 -0
- package/src/config/index.ts +5 -0
- package/src/config/model-constants.ts +0 -3
- package/src/config/workstream-defaults.ts +4 -0
- package/src/db/cursor-pagination.ts +2 -2
- package/src/db/index.ts +10 -0
- package/src/db/memory.ts +9 -15
- package/src/document/index.ts +2 -0
- package/src/document/parsing.ts +0 -25
- package/src/embeddings/provider.ts +17 -8
- package/src/index.ts +15 -505
- package/src/queues/index.ts +10 -0
- package/src/redis/connection-accessor.ts +26 -0
- package/src/redis/connection.ts +1 -1
- package/src/redis/index.ts +9 -25
- package/src/redis/org-memory-lock.ts +1 -1
- package/src/redis/redis-lease-lock.ts +1 -1
- package/src/redis/stream-context.ts +12 -2
- package/src/runtime/agent-runtime-policy.ts +9 -5
- package/src/runtime/agent-stream-helpers.ts +6 -3
- package/src/runtime/agent-types.ts +1 -5
- package/src/runtime/approval-continuation.ts +9 -1
- package/src/runtime/chat-attachments.ts +1 -1
- package/src/runtime/chat-request-routing.ts +1 -1
- package/src/runtime/context-compaction-runtime.ts +2 -2
- package/src/runtime/context-compaction.ts +1 -1
- package/src/runtime/execution-plan.ts +1 -1
- package/src/runtime/index.ts +26 -0
- package/src/runtime/indexed-repositories-policy.ts +10 -10
- package/src/runtime/memory-pipeline.ts +0 -2
- package/src/runtime/runtime-config.ts +238 -0
- package/src/runtime/runtime-extensions.ts +3 -2
- package/src/runtime/runtime-worker-registry.ts +47 -0
- package/src/runtime/team-consultation-orchestrator.ts +9 -6
- package/src/runtime/team-consultation-prompts.ts +3 -2
- package/src/runtime/turn-lifecycle.ts +1 -1
- package/src/runtime/workstream-chat-helpers.ts +0 -54
- package/src/runtime/workstream-routing-policy.ts +3 -7
- package/src/runtime.ts +387 -0
- package/src/services/chat-attachments.service.ts +1 -1
- package/src/services/context-compaction.service.ts +1 -1
- package/src/services/execution-plan.service.ts +14 -16
- package/src/services/index.ts +14 -0
- package/src/services/learned-skill.service.ts +80 -37
- package/src/services/memory.service.ts +5 -4
- package/src/services/mutating-approval.service.ts +1 -1
- package/src/services/organization-member.service.ts +1 -1
- package/src/services/organization.service.ts +1 -1
- package/src/services/plan-approval.service.ts +2 -2
- package/src/services/plan-artifact.service.ts +2 -3
- package/src/services/plan-builder.service.ts +1 -1
- package/src/services/plan-checkpoint.service.ts +2 -2
- package/src/services/plan-compiler.service.ts +2 -2
- package/src/services/plan-executor.service.ts +10 -9
- package/src/services/plan-run.service.ts +2 -2
- package/src/services/plan-validator.service.ts +4 -4
- package/src/services/recent-activity-title.service.ts +1 -1
- package/src/services/recent-activity.service.ts +14 -16
- package/src/services/user.service.ts +2 -2
- package/src/services/workstream-message.service.ts +2 -3
- package/src/services/workstream-title.service.ts +1 -1
- package/src/services/workstream-turn-preparation.ts +105 -50
- package/src/services/workstream-turn.ts +14 -1
- package/src/services/workstream.service.ts +9 -9
- package/src/storage/attachment-parser.ts +1 -1
- package/src/storage/attachment-storage.service.ts +11 -10
- package/src/storage/generated-document-storage.service.ts +7 -6
- package/src/storage/index.ts +10 -0
- package/src/system-agents/delegated-agent-factory.ts +78 -29
- package/src/system-agents/index.ts +4 -0
- package/src/system-agents/recent-activity-title-refiner.agent.ts +38 -3
- package/src/system-agents/regular-chat-memory-digest.agent.ts +1 -1
- package/src/system-agents/skill-extractor.agent.ts +1 -1
- package/src/system-agents/skill-manager.agent.ts +2 -4
- package/src/tools/execution-plan.tool.ts +2 -2
- package/src/tools/firecrawl-client.ts +2 -2
- package/src/tools/index.ts +12 -0
- package/src/tools/research-topic.tool.ts +1 -1
- package/src/tools/team-think.tool.ts +1 -1
- package/src/tools/user-questions.tool.ts +2 -2
- package/src/utils/index.ts +6 -0
- package/src/workers/bootstrap.ts +8 -16
- package/src/workers/index.ts +7 -0
- package/src/workers/regular-chat-memory-digest.runner.ts +1 -1
- package/src/workers/skill-extraction.runner.ts +1 -1
- package/src/workers/utils/{repo-indexer-chunker.ts → file-section-chunker.ts} +23 -52
- package/src/workers/utils/repo-structure-extractor.ts +2 -5
- package/src/workers/utils/repomix-file-sections.ts +42 -0
- package/src/config/env-shapes.ts +0 -121
- package/src/runtime/agent-contract.ts +0 -1
package/src/index.ts
CHANGED
|
@@ -1,505 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
import type { RedisConnectionManager } from './redis/connection'
|
|
17
|
-
import type { isApprovalContinuationRequest } from './runtime/approval-continuation'
|
|
18
|
-
import type { routeWorkstreamChatMessages } from './runtime/chat-request-routing'
|
|
19
|
-
import type { LotaPlugin } from './runtime/plugin-types'
|
|
20
|
-
import type { LotaRuntimeAdapters, LotaRuntimeTurnHooks } from './runtime/runtime-extensions'
|
|
21
|
-
import type { attachmentService } from './services/attachment.service'
|
|
22
|
-
import type { documentChunkService } from './services/document-chunk.service'
|
|
23
|
-
import type { executionPlanService } from './services/execution-plan.service'
|
|
24
|
-
import type { memoryService } from './services/memory.service'
|
|
25
|
-
import type { verifyMutatingApproval } from './services/mutating-approval.service'
|
|
26
|
-
import type { organizationMemberService } from './services/organization-member.service'
|
|
27
|
-
import type { organizationService } from './services/organization.service'
|
|
28
|
-
import type { recentActivityTitleService } from './services/recent-activity-title.service'
|
|
29
|
-
import type { recentActivityService } from './services/recent-activity.service'
|
|
30
|
-
import type { userService } from './services/user.service'
|
|
31
|
-
import type { workstreamMessageService } from './services/workstream-message.service'
|
|
32
|
-
import type { workstreamTitleService } from './services/workstream-title.service'
|
|
33
|
-
import type {
|
|
34
|
-
createWorkstreamApprovalContinuationStream,
|
|
35
|
-
createWorkstreamNativeToolApprovalStream,
|
|
36
|
-
createWorkstreamTurnStream,
|
|
37
|
-
runWorkstreamTurnInBackground,
|
|
38
|
-
} from './services/workstream-turn'
|
|
39
|
-
import type { workstreamService } from './services/workstream.service'
|
|
40
|
-
import type { generatedDocumentStorageService } from './storage/generated-document-storage.service'
|
|
41
|
-
|
|
42
|
-
export type LotaAgentFactoryRegistry = Record<string, (...args: unknown[]) => unknown>
|
|
43
|
-
|
|
44
|
-
interface LotaRuntimeBuiltInWorkers {
|
|
45
|
-
startContextCompactionWorker: typeof startContextCompactionWorker
|
|
46
|
-
startMemoryConsolidationWorker: typeof startMemoryConsolidationWorker
|
|
47
|
-
startPostChatMemoryWorker: typeof startPostChatMemoryWorker
|
|
48
|
-
startRecentActivityTitleRefinementWorker: typeof startRecentActivityTitleRefinementWorker
|
|
49
|
-
startRegularChatMemoryDigestWorker: typeof startRegularChatMemoryDigestWorker
|
|
50
|
-
startSkillExtractionWorker: typeof startSkillExtractionWorker
|
|
51
|
-
startWorkstreamTitleGenerationWorker: typeof startWorkstreamTitleGenerationWorker
|
|
52
|
-
scheduleRecurringConsolidation: typeof scheduleRecurringConsolidation
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
type ArchiveSdkWorkstream = (
|
|
56
|
-
workstreamId: Parameters<typeof workstreamService.updateStatus>[0],
|
|
57
|
-
status?: 'archived',
|
|
58
|
-
) => ReturnType<typeof workstreamService.updateStatus>
|
|
59
|
-
|
|
60
|
-
type UnarchiveSdkWorkstream = (
|
|
61
|
-
workstreamId: Parameters<typeof workstreamService.updateStatus>[0],
|
|
62
|
-
status?: 'regular',
|
|
63
|
-
) => ReturnType<typeof workstreamService.updateStatus>
|
|
64
|
-
|
|
65
|
-
export interface LotaRuntimeConfig {
|
|
66
|
-
database: { url: string; namespace: string; username: string; password: string }
|
|
67
|
-
redis: { url: string }
|
|
68
|
-
aiGateway: { url: string; key: string; admin?: string; pass?: string; embeddingModel?: string }
|
|
69
|
-
s3: {
|
|
70
|
-
endpoint: string
|
|
71
|
-
bucket: string
|
|
72
|
-
region?: string
|
|
73
|
-
accessKeyId: string
|
|
74
|
-
secretAccessKey: string
|
|
75
|
-
attachmentUrlExpiresIn?: number
|
|
76
|
-
}
|
|
77
|
-
firecrawl: { apiKey: string; apiBaseUrl?: string }
|
|
78
|
-
logging?: { level?: 'trace' | 'debug' | 'info' | 'warning' | 'error' | 'fatal' }
|
|
79
|
-
memory?: { searchK?: number; embeddingCacheTtlSeconds?: number }
|
|
80
|
-
workstreams?: LotaWorkstreamConfig
|
|
81
|
-
backgroundProcessing?: {
|
|
82
|
-
memoryExtractionFrequency?: number
|
|
83
|
-
skillExtractionFrequency?: number
|
|
84
|
-
memoryDigestFrequency?: number
|
|
85
|
-
memoryConsolidationFrequency?: number
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
agents: {
|
|
89
|
-
roster: readonly string[]
|
|
90
|
-
displayNames: Record<string, string>
|
|
91
|
-
shortDisplayNames?: Record<string, string>
|
|
92
|
-
teamConsultParticipants: readonly string[]
|
|
93
|
-
getCoreWorkstreamProfile?: (coreType: string) => CoreWorkstreamProfile
|
|
94
|
-
createAgent?: LotaAgentFactoryRegistry
|
|
95
|
-
buildAgentTools?: (...args: unknown[]) => unknown
|
|
96
|
-
getAgentRuntimeConfig?: (...args: unknown[]) => unknown
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
toolProviders?: Record<string, unknown>
|
|
100
|
-
extraSchemaFiles?: Array<string | URL>
|
|
101
|
-
extraWorkers?: Record<string, unknown>
|
|
102
|
-
pluginRuntime?: Record<string, LotaPlugin>
|
|
103
|
-
runtimeAdapters?: LotaRuntimeAdapters
|
|
104
|
-
turnHooks?: LotaRuntimeTurnHooks
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
export interface LotaRuntime {
|
|
108
|
-
services: {
|
|
109
|
-
database: SurrealDBService
|
|
110
|
-
databaseService: SurrealDBService
|
|
111
|
-
redis: RedisConnectionManager
|
|
112
|
-
closeRedisConnection: () => Promise<void>
|
|
113
|
-
attachmentService: typeof attachmentService
|
|
114
|
-
documentChunkService: typeof documentChunkService
|
|
115
|
-
generatedDocumentStorageService: typeof generatedDocumentStorageService
|
|
116
|
-
memoryService: typeof memoryService
|
|
117
|
-
verifyMutatingApproval: typeof verifyMutatingApproval
|
|
118
|
-
organizationService: typeof organizationService
|
|
119
|
-
organizationMemberService: typeof organizationMemberService
|
|
120
|
-
userService: typeof userService
|
|
121
|
-
recentActivityService: typeof recentActivityService
|
|
122
|
-
recentActivityTitleService: typeof recentActivityTitleService
|
|
123
|
-
executionPlanService: typeof executionPlanService
|
|
124
|
-
workstreamMessageService: typeof workstreamMessageService
|
|
125
|
-
workstreamService: typeof workstreamService
|
|
126
|
-
workstreamTitleService: typeof workstreamTitleService
|
|
127
|
-
createWorkstreamApprovalContinuationStream: typeof createWorkstreamApprovalContinuationStream
|
|
128
|
-
createWorkstreamNativeToolApprovalStream: typeof createWorkstreamNativeToolApprovalStream
|
|
129
|
-
createWorkstreamTurnStream: typeof createWorkstreamTurnStream
|
|
130
|
-
isApprovalContinuationRequest: typeof isApprovalContinuationRequest
|
|
131
|
-
runWorkstreamTurnInBackground: typeof runWorkstreamTurnInBackground
|
|
132
|
-
}
|
|
133
|
-
lota: {
|
|
134
|
-
organizations: {
|
|
135
|
-
create: typeof organizationService.createOrganization
|
|
136
|
-
upsert: typeof organizationService.upsertOrganization
|
|
137
|
-
get: typeof organizationService.getOrganization
|
|
138
|
-
list: typeof organizationService.listOrganizations
|
|
139
|
-
update: typeof organizationService.updateOrganization
|
|
140
|
-
delete: typeof organizationService.deleteOrganization
|
|
141
|
-
}
|
|
142
|
-
users: {
|
|
143
|
-
upsert: typeof userService.upsertUser
|
|
144
|
-
get: typeof userService.getUser
|
|
145
|
-
list: typeof userService.listUsers
|
|
146
|
-
update: typeof userService.updateUser
|
|
147
|
-
delete: typeof userService.deleteUser
|
|
148
|
-
}
|
|
149
|
-
memberships: {
|
|
150
|
-
add: typeof organizationMemberService.addMembership
|
|
151
|
-
listForOrganization: typeof organizationMemberService.listMembershipsForOrganization
|
|
152
|
-
listForUser: typeof organizationMemberService.listMembershipsForUser
|
|
153
|
-
remove: typeof organizationMemberService.removeMembership
|
|
154
|
-
isMember: typeof organizationMemberService.isMember
|
|
155
|
-
}
|
|
156
|
-
workstreams: {
|
|
157
|
-
create: typeof workstreamService.createWorkstream
|
|
158
|
-
list: typeof workstreamService.listWorkstreams
|
|
159
|
-
get: typeof workstreamService.getWorkstream
|
|
160
|
-
update: typeof workstreamService.updateTitle
|
|
161
|
-
archive: ArchiveSdkWorkstream
|
|
162
|
-
unarchive: UnarchiveSdkWorkstream
|
|
163
|
-
delete: typeof workstreamService.deleteWorkstream
|
|
164
|
-
stop: typeof workstreamService.stopActiveRun
|
|
165
|
-
listMessages: typeof workstreamMessageService.listMessageHistoryPage
|
|
166
|
-
getMessage: (params: { workstreamId: string; messageId: string }) => Promise<unknown>
|
|
167
|
-
sendMessage: (params: {
|
|
168
|
-
workstreamId: string
|
|
169
|
-
organizationId: string
|
|
170
|
-
userId: string
|
|
171
|
-
userName: string
|
|
172
|
-
messages: Parameters<typeof routeWorkstreamChatMessages>[0]
|
|
173
|
-
}) => Promise<Awaited<ReturnType<typeof createWorkstreamTurnStream>>>
|
|
174
|
-
continueApproval: (params: {
|
|
175
|
-
workstreamId: string
|
|
176
|
-
organizationId: string
|
|
177
|
-
userId: string
|
|
178
|
-
userName: string
|
|
179
|
-
messages: Parameters<typeof routeWorkstreamChatMessages>[0]
|
|
180
|
-
}) => Promise<Awaited<ReturnType<typeof createWorkstreamApprovalContinuationStream>>>
|
|
181
|
-
uploadAttachment: typeof attachmentService.uploadWorkstreamAttachment
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
redis: {
|
|
185
|
-
manager: RedisConnectionManager
|
|
186
|
-
getConnection: () => ReturnType<RedisConnectionManager['getConnection']>
|
|
187
|
-
getConnectionForBullMQ: () => ReturnType<RedisConnectionManager['getConnectionForBullMQ']>
|
|
188
|
-
closeConnection: () => Promise<void>
|
|
189
|
-
}
|
|
190
|
-
workers: LotaRuntimeBuiltInWorkers & Record<string, unknown>
|
|
191
|
-
schemaFiles: Array<string | URL>
|
|
192
|
-
contributions: { envKeys: readonly string[]; schemaFiles: Array<string | URL> }
|
|
193
|
-
config: LotaRuntimeConfig
|
|
194
|
-
plugins: Record<string, LotaPlugin>
|
|
195
|
-
connectPluginDatabases(): Promise<void>
|
|
196
|
-
connect(): Promise<void>
|
|
197
|
-
disconnect(): Promise<void>
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
export async function createLotaRuntime(config: LotaRuntimeConfig): Promise<LotaRuntime> {
|
|
201
|
-
const { lotaSdkEnvKeys, setEnv } = await import('./config/env-shapes')
|
|
202
|
-
const { configureLogger } = await import('./config/logger')
|
|
203
|
-
const { publishDatabaseBootstrap } = await import('./db/startup')
|
|
204
|
-
const { computeSchemaFingerprint } = await import('./db/schema-fingerprint')
|
|
205
|
-
const { LOTA_SDK_DATABASE_NAME } = await import('./db/sdk-database')
|
|
206
|
-
const { SurrealDBService: SurrealDBServiceClass, setDatabaseService } = await import('./db/service')
|
|
207
|
-
const { createRedisConnectionManager } = await import('./redis/connection')
|
|
208
|
-
const { setRedisConnectionManager } = await import('./redis/index')
|
|
209
|
-
const { configureAgents, configureAgentFactory } = await import('./config/agent-defaults')
|
|
210
|
-
const { configureWorkstreams } = await import('./config/workstream-defaults')
|
|
211
|
-
const { configureRuntimeExtensions } = await import('./runtime/runtime-extensions')
|
|
212
|
-
const { routeWorkstreamChatMessages } = await import('./runtime/chat-request-routing')
|
|
213
|
-
const { configureBackgroundProcessing } = await import('./config/background-processing')
|
|
214
|
-
const { configureEmbeddingCache } = await import('./ai/embedding-cache')
|
|
215
|
-
|
|
216
|
-
// Resolve config defaults
|
|
217
|
-
const memory = {
|
|
218
|
-
searchK: config.memory?.searchK ?? 6,
|
|
219
|
-
embeddingCacheTtlSeconds: config.memory?.embeddingCacheTtlSeconds ?? 3600,
|
|
220
|
-
}
|
|
221
|
-
const backgroundProcessing = {
|
|
222
|
-
memoryExtractionFrequency: config.backgroundProcessing?.memoryExtractionFrequency ?? 3,
|
|
223
|
-
skillExtractionFrequency: config.backgroundProcessing?.skillExtractionFrequency ?? 5,
|
|
224
|
-
memoryDigestFrequency: config.backgroundProcessing?.memoryDigestFrequency ?? 1,
|
|
225
|
-
memoryConsolidationFrequency: config.backgroundProcessing?.memoryConsolidationFrequency ?? 10,
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
setEnv({
|
|
229
|
-
AI_GATEWAY_URL: config.aiGateway.url,
|
|
230
|
-
AI_GATEWAY_KEY: config.aiGateway.key,
|
|
231
|
-
AI_GATEWAY_ADMIN: config.aiGateway.admin,
|
|
232
|
-
AI_GATEWAY_PASS: config.aiGateway.pass,
|
|
233
|
-
AI_EMBEDDING_MODEL: config.aiGateway.embeddingModel ?? 'openai/text-embedding-3-small',
|
|
234
|
-
REDIS_URL: config.redis.url,
|
|
235
|
-
LOG_LEVEL: config.logging?.level ?? 'info',
|
|
236
|
-
S3_ENDPOINT: config.s3.endpoint,
|
|
237
|
-
S3_BUCKET: config.s3.bucket,
|
|
238
|
-
S3_REGION: config.s3.region ?? 'garage',
|
|
239
|
-
S3_ACCESS_KEY_ID: config.s3.accessKeyId,
|
|
240
|
-
S3_SECRET_ACCESS_KEY: config.s3.secretAccessKey,
|
|
241
|
-
ATTACHMENT_URL_EXPIRES_IN: config.s3.attachmentUrlExpiresIn ?? 1800,
|
|
242
|
-
FIRECRAWL_API_KEY: config.firecrawl.apiKey,
|
|
243
|
-
FIRECRAWL_API_BASE_URL: config.firecrawl.apiBaseUrl,
|
|
244
|
-
MEMORY_SEARCH_K: memory.searchK,
|
|
245
|
-
})
|
|
246
|
-
|
|
247
|
-
await configureLogger(config.logging?.level ?? 'info')
|
|
248
|
-
|
|
249
|
-
const db = new SurrealDBServiceClass({
|
|
250
|
-
url: config.database.url,
|
|
251
|
-
namespace: config.database.namespace,
|
|
252
|
-
database: LOTA_SDK_DATABASE_NAME,
|
|
253
|
-
username: config.database.username,
|
|
254
|
-
password: config.database.password,
|
|
255
|
-
})
|
|
256
|
-
setDatabaseService(db)
|
|
257
|
-
|
|
258
|
-
const redisManager = createRedisConnectionManager({ url: config.redis.url })
|
|
259
|
-
setRedisConnectionManager(redisManager)
|
|
260
|
-
configureEmbeddingCache(redisManager.getConnection(), memory.embeddingCacheTtlSeconds)
|
|
261
|
-
configureBackgroundProcessing(backgroundProcessing)
|
|
262
|
-
|
|
263
|
-
configureAgents({
|
|
264
|
-
roster: config.agents.roster,
|
|
265
|
-
displayNames: config.agents.displayNames,
|
|
266
|
-
shortDisplayNames: config.agents.shortDisplayNames,
|
|
267
|
-
teamConsultParticipants: config.agents.teamConsultParticipants,
|
|
268
|
-
getCoreWorkstreamProfile: config.agents.getCoreWorkstreamProfile,
|
|
269
|
-
})
|
|
270
|
-
configureWorkstreams({ agentRoster: config.agents.roster, config: config.workstreams })
|
|
271
|
-
|
|
272
|
-
if (config.agents.createAgent || config.agents.buildAgentTools || config.agents.getAgentRuntimeConfig) {
|
|
273
|
-
configureAgentFactory({
|
|
274
|
-
createAgent: config.agents.createAgent ?? {},
|
|
275
|
-
buildAgentTools: config.agents.buildAgentTools,
|
|
276
|
-
getAgentRuntimeConfig: config.agents.getAgentRuntimeConfig,
|
|
277
|
-
pluginRuntime: config.pluginRuntime,
|
|
278
|
-
})
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
const { attachmentService } = await import('./services/attachment.service')
|
|
282
|
-
const { documentChunkService } = await import('./services/document-chunk.service')
|
|
283
|
-
const { recentActivityService } = await import('./services/recent-activity.service')
|
|
284
|
-
const { recentActivityTitleService } = await import('./services/recent-activity-title.service')
|
|
285
|
-
const { executionPlanService } = await import('./services/execution-plan.service')
|
|
286
|
-
const { memoryService } = await import('./services/memory.service')
|
|
287
|
-
const { verifyMutatingApproval } = await import('./services/mutating-approval.service')
|
|
288
|
-
const { organizationMemberService } = await import('./services/organization-member.service')
|
|
289
|
-
const { organizationService } = await import('./services/organization.service')
|
|
290
|
-
const { userService } = await import('./services/user.service')
|
|
291
|
-
const { workstreamMessageService } = await import('./services/workstream-message.service')
|
|
292
|
-
const { workstreamService } = await import('./services/workstream.service')
|
|
293
|
-
const { workstreamTitleService } = await import('./services/workstream-title.service')
|
|
294
|
-
const {
|
|
295
|
-
createWorkstreamApprovalContinuationStream,
|
|
296
|
-
createWorkstreamNativeToolApprovalStream,
|
|
297
|
-
createWorkstreamTurnStream,
|
|
298
|
-
isApprovalContinuationRequest,
|
|
299
|
-
runWorkstreamTurnInBackground,
|
|
300
|
-
} = await import('./services/workstream-turn')
|
|
301
|
-
const { generatedDocumentStorageService } = await import('./storage/generated-document-storage.service')
|
|
302
|
-
const { startContextCompactionWorker } = await import('./queues/context-compaction.queue')
|
|
303
|
-
const { scheduleRecurringConsolidation, startMemoryConsolidationWorker } =
|
|
304
|
-
await import('./queues/memory-consolidation.queue')
|
|
305
|
-
const { startPostChatMemoryWorker } = await import('./queues/post-chat-memory.queue')
|
|
306
|
-
const { startRecentActivityTitleRefinementWorker } = await import('./queues/recent-activity-title-refinement.queue')
|
|
307
|
-
const { startRegularChatMemoryDigestWorker } = await import('./queues/regular-chat-memory-digest.queue')
|
|
308
|
-
const { startSkillExtractionWorker } = await import('./queues/skill-extraction.queue')
|
|
309
|
-
const { startWorkstreamTitleGenerationWorker } = await import('./queues/workstream-title-generation.queue')
|
|
310
|
-
|
|
311
|
-
configureRuntimeExtensions({
|
|
312
|
-
adapters: config.runtimeAdapters,
|
|
313
|
-
turnHooks: config.turnHooks,
|
|
314
|
-
toolProviders: (config.toolProviders ?? {}) as never,
|
|
315
|
-
extraWorkers: config.extraWorkers,
|
|
316
|
-
})
|
|
317
|
-
|
|
318
|
-
const pluginRuntime = config.pluginRuntime ?? {}
|
|
319
|
-
const pluginContributions = Object.values(pluginRuntime).map((plugin) => plugin.contributions)
|
|
320
|
-
const schemaFiles = [...getBuiltInSchemaFiles(), ...(config.extraSchemaFiles ?? [])]
|
|
321
|
-
const hostContributionSchemaFiles = pluginContributions.flatMap((plugin) => plugin.schemaFiles)
|
|
322
|
-
const contributionEnvKeys = [...lotaSdkEnvKeys, ...pluginContributions.flatMap((plugin) => plugin.envKeys)]
|
|
323
|
-
const connectPluginDatabases = createPluginDatabaseConnector(pluginRuntime)
|
|
324
|
-
const builtInWorkers = {
|
|
325
|
-
startContextCompactionWorker,
|
|
326
|
-
startMemoryConsolidationWorker,
|
|
327
|
-
startPostChatMemoryWorker,
|
|
328
|
-
startRecentActivityTitleRefinementWorker,
|
|
329
|
-
startRegularChatMemoryDigestWorker,
|
|
330
|
-
startSkillExtractionWorker,
|
|
331
|
-
startWorkstreamTitleGenerationWorker,
|
|
332
|
-
scheduleRecurringConsolidation,
|
|
333
|
-
} satisfies LotaRuntimeBuiltInWorkers
|
|
334
|
-
|
|
335
|
-
const lota = {
|
|
336
|
-
organizations: {
|
|
337
|
-
create: organizationService.createOrganization.bind(organizationService),
|
|
338
|
-
upsert: organizationService.upsertOrganization.bind(organizationService),
|
|
339
|
-
get: organizationService.getOrganization.bind(organizationService),
|
|
340
|
-
list: organizationService.listOrganizations.bind(organizationService),
|
|
341
|
-
update: organizationService.updateOrganization.bind(organizationService),
|
|
342
|
-
delete: organizationService.deleteOrganization.bind(organizationService),
|
|
343
|
-
},
|
|
344
|
-
users: {
|
|
345
|
-
upsert: userService.upsertUser.bind(userService),
|
|
346
|
-
get: userService.getUser.bind(userService),
|
|
347
|
-
list: userService.listUsers.bind(userService),
|
|
348
|
-
update: userService.updateUser.bind(userService),
|
|
349
|
-
delete: userService.deleteUser.bind(userService),
|
|
350
|
-
},
|
|
351
|
-
memberships: {
|
|
352
|
-
add: organizationMemberService.addMembership.bind(organizationMemberService),
|
|
353
|
-
listForOrganization: organizationMemberService.listMembershipsForOrganization.bind(organizationMemberService),
|
|
354
|
-
listForUser: organizationMemberService.listMembershipsForUser.bind(organizationMemberService),
|
|
355
|
-
remove: organizationMemberService.removeMembership.bind(organizationMemberService),
|
|
356
|
-
isMember: organizationMemberService.isMember.bind(organizationMemberService),
|
|
357
|
-
},
|
|
358
|
-
workstreams: {
|
|
359
|
-
create: workstreamService.createWorkstream.bind(workstreamService),
|
|
360
|
-
list: workstreamService.listWorkstreams.bind(workstreamService),
|
|
361
|
-
get: workstreamService.getWorkstream.bind(workstreamService),
|
|
362
|
-
update: workstreamService.updateTitle.bind(workstreamService),
|
|
363
|
-
archive: async (workstreamId, status = 'archived') => await workstreamService.updateStatus(workstreamId, status),
|
|
364
|
-
unarchive: async (workstreamId, status = 'regular') => await workstreamService.updateStatus(workstreamId, status),
|
|
365
|
-
delete: workstreamService.deleteWorkstream.bind(workstreamService),
|
|
366
|
-
stop: workstreamService.stopActiveRun.bind(workstreamService),
|
|
367
|
-
listMessages: workstreamMessageService.listMessageHistoryPage.bind(workstreamMessageService),
|
|
368
|
-
getMessage: async ({ workstreamId, messageId }) => {
|
|
369
|
-
const messages = await workstreamMessageService.listMessages(ensureRecordId(workstreamId, TABLES.WORKSTREAM))
|
|
370
|
-
const message = messages.find((candidate) => candidate.id === messageId)
|
|
371
|
-
if (!message) {
|
|
372
|
-
throw new Error(`Workstream message not found: ${messageId}`)
|
|
373
|
-
}
|
|
374
|
-
return message
|
|
375
|
-
},
|
|
376
|
-
sendMessage: async ({ workstreamId, organizationId, userId, userName, messages }) => {
|
|
377
|
-
const workstreamRef = ensureRecordId(workstreamId, TABLES.WORKSTREAM)
|
|
378
|
-
const workstream = await workstreamService.getWorkstream(workstreamRef)
|
|
379
|
-
const routed = routeWorkstreamChatMessages(messages)
|
|
380
|
-
if (routed.kind !== 'turn') {
|
|
381
|
-
throw new Error(routed.kind === 'invalid' ? routed.message : 'Expected a user turn payload.')
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
return await createWorkstreamTurnStream({
|
|
385
|
-
workstream,
|
|
386
|
-
workstreamRef,
|
|
387
|
-
orgRef: ensureRecordId(organizationId, TABLES.ORGANIZATION),
|
|
388
|
-
userRef: ensureRecordId(userId, TABLES.USER),
|
|
389
|
-
userName,
|
|
390
|
-
inputMessage: routed.inputMessage,
|
|
391
|
-
})
|
|
392
|
-
},
|
|
393
|
-
continueApproval: async ({ workstreamId, organizationId, userId, userName, messages }) => {
|
|
394
|
-
const workstreamRef = ensureRecordId(workstreamId, TABLES.WORKSTREAM)
|
|
395
|
-
const workstream = await workstreamService.getWorkstream(workstreamRef)
|
|
396
|
-
const routed = routeWorkstreamChatMessages(messages)
|
|
397
|
-
if (routed.kind !== 'approval-continuation') {
|
|
398
|
-
throw new Error(
|
|
399
|
-
routed.kind === 'invalid' ? routed.message : 'Expected approval continuation messages payload.',
|
|
400
|
-
)
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
return await createWorkstreamApprovalContinuationStream({
|
|
404
|
-
workstream,
|
|
405
|
-
workstreamRef,
|
|
406
|
-
orgRef: ensureRecordId(organizationId, TABLES.ORGANIZATION),
|
|
407
|
-
userRef: ensureRecordId(userId, TABLES.USER),
|
|
408
|
-
userName,
|
|
409
|
-
approvalMessages: routed.approvalMessages,
|
|
410
|
-
})
|
|
411
|
-
},
|
|
412
|
-
uploadAttachment: attachmentService.uploadWorkstreamAttachment.bind(attachmentService),
|
|
413
|
-
},
|
|
414
|
-
} satisfies LotaRuntime['lota']
|
|
415
|
-
|
|
416
|
-
return {
|
|
417
|
-
services: {
|
|
418
|
-
database: db,
|
|
419
|
-
databaseService: db,
|
|
420
|
-
redis: redisManager,
|
|
421
|
-
closeRedisConnection: async () => await redisManager.closeConnection(),
|
|
422
|
-
attachmentService,
|
|
423
|
-
documentChunkService,
|
|
424
|
-
generatedDocumentStorageService,
|
|
425
|
-
memoryService,
|
|
426
|
-
verifyMutatingApproval,
|
|
427
|
-
organizationService,
|
|
428
|
-
organizationMemberService,
|
|
429
|
-
userService,
|
|
430
|
-
recentActivityService,
|
|
431
|
-
recentActivityTitleService,
|
|
432
|
-
executionPlanService,
|
|
433
|
-
workstreamMessageService,
|
|
434
|
-
workstreamService,
|
|
435
|
-
workstreamTitleService,
|
|
436
|
-
createWorkstreamApprovalContinuationStream,
|
|
437
|
-
createWorkstreamNativeToolApprovalStream,
|
|
438
|
-
createWorkstreamTurnStream,
|
|
439
|
-
isApprovalContinuationRequest,
|
|
440
|
-
runWorkstreamTurnInBackground,
|
|
441
|
-
},
|
|
442
|
-
lota,
|
|
443
|
-
redis: {
|
|
444
|
-
manager: redisManager,
|
|
445
|
-
getConnection: () => redisManager.getConnection(),
|
|
446
|
-
getConnectionForBullMQ: () => redisManager.getConnectionForBullMQ(),
|
|
447
|
-
closeConnection: async () => await redisManager.closeConnection(),
|
|
448
|
-
},
|
|
449
|
-
workers: { ...builtInWorkers, ...config.extraWorkers },
|
|
450
|
-
schemaFiles,
|
|
451
|
-
contributions: { envKeys: [...new Set(contributionEnvKeys)], schemaFiles: hostContributionSchemaFiles },
|
|
452
|
-
config,
|
|
453
|
-
plugins: pluginRuntime,
|
|
454
|
-
async connectPluginDatabases() {
|
|
455
|
-
await connectPluginDatabases()
|
|
456
|
-
},
|
|
457
|
-
async connect() {
|
|
458
|
-
await db.connect()
|
|
459
|
-
const bunFiles = schemaFiles.map((schemaFile) =>
|
|
460
|
-
schemaFile instanceof URL ? Bun.file(schemaFile.pathname) : Bun.file(schemaFile),
|
|
461
|
-
)
|
|
462
|
-
await db.applySchemaAndMigrations(bunFiles)
|
|
463
|
-
const schemaFingerprint = await computeSchemaFingerprint(schemaFiles)
|
|
464
|
-
await publishDatabaseBootstrap({ databaseService: db, schemaFingerprint })
|
|
465
|
-
},
|
|
466
|
-
async disconnect() {
|
|
467
|
-
await db.disconnect()
|
|
468
|
-
await redisManager.closeConnection()
|
|
469
|
-
},
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
function getBuiltInSchemaFiles(): URL[] {
|
|
474
|
-
return [
|
|
475
|
-
new URL('../infrastructure/schema/00_identity.surql', import.meta.url),
|
|
476
|
-
new URL('../infrastructure/schema/00_workstream.surql', import.meta.url),
|
|
477
|
-
new URL('../infrastructure/schema/01_memory.surql', import.meta.url),
|
|
478
|
-
new URL('../infrastructure/schema/02_execution_plan.surql', import.meta.url),
|
|
479
|
-
new URL('../infrastructure/schema/03_learned_skill.surql', import.meta.url),
|
|
480
|
-
new URL('../infrastructure/schema/05_recent_activity.surql', import.meta.url),
|
|
481
|
-
new URL('../infrastructure/schema/04_runtime_bootstrap.surql', import.meta.url),
|
|
482
|
-
]
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
function createPluginDatabaseConnector(pluginRuntime: Record<string, LotaPlugin>): () => Promise<void> {
|
|
486
|
-
return async () => {
|
|
487
|
-
for (const plugin of Object.values(pluginRuntime)) {
|
|
488
|
-
const services = plugin.services as Record<string, unknown>
|
|
489
|
-
const connectDatabase = services.connectDatabase
|
|
490
|
-
if (typeof connectDatabase !== 'function') {
|
|
491
|
-
continue
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
await Reflect.apply(connectDatabase, services, [])
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
export type { CoreWorkstreamProfile } from './config/agent-defaults'
|
|
500
|
-
export type { SurrealDBService } from './db/service'
|
|
501
|
-
export type { RedisConnectionManager } from './redis/connection'
|
|
502
|
-
export { createWorkstreamResumableContext } from './redis/stream-context'
|
|
503
|
-
export type { LotaPlugin, LotaPluginContributions } from './runtime/plugin-types'
|
|
504
|
-
export type { LotaRuntimeAdapters, LotaRuntimeTurnHooks } from './runtime/runtime-extensions'
|
|
505
|
-
export { createLogHelloWorldTool } from './tools/log-hello-world.tool'
|
|
1
|
+
export * from './runtime'
|
|
2
|
+
export * from './ai'
|
|
3
|
+
export * from './bifrost'
|
|
4
|
+
export * from './config'
|
|
5
|
+
export * from './db'
|
|
6
|
+
export * from './document'
|
|
7
|
+
export * from './queues'
|
|
8
|
+
export * from './redis'
|
|
9
|
+
export * from './runtime/index'
|
|
10
|
+
export * from './services'
|
|
11
|
+
export * from './storage'
|
|
12
|
+
export * from './system-agents'
|
|
13
|
+
export * from './tools'
|
|
14
|
+
export * from './utils'
|
|
15
|
+
export * from './workers'
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from './context-compaction.queue'
|
|
2
|
+
export * from './document-processor.queue'
|
|
3
|
+
export * from './memory-consolidation.queue'
|
|
4
|
+
export * from './post-chat-memory.queue'
|
|
5
|
+
export * from './recent-activity-title-refinement.queue'
|
|
6
|
+
export * from './regular-chat-memory-digest.config'
|
|
7
|
+
export * from './regular-chat-memory-digest.queue'
|
|
8
|
+
export * from './skill-extraction.config'
|
|
9
|
+
export * from './skill-extraction.queue'
|
|
10
|
+
export * from './workstream-title-generation.queue'
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type IORedis from 'ioredis'
|
|
2
|
+
|
|
3
|
+
export interface RedisConnectionAccessor {
|
|
4
|
+
getConnection(): IORedis
|
|
5
|
+
getConnectionForBullMQ(): IORedis
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
let redisManager: RedisConnectionAccessor | undefined
|
|
9
|
+
|
|
10
|
+
export function setRedisConnectionManager(manager: RedisConnectionAccessor): void {
|
|
11
|
+
redisManager = manager
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function getRedisConnection(): IORedis {
|
|
15
|
+
if (!redisManager) {
|
|
16
|
+
throw new Error('Redis connection manager not configured. Call setRedisConnectionManager() first.')
|
|
17
|
+
}
|
|
18
|
+
return redisManager.getConnection()
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function getRedisConnectionForBullMQ(): IORedis {
|
|
22
|
+
if (!redisManager) {
|
|
23
|
+
throw new Error('Redis connection manager not configured. Call setRedisConnectionManager() first.')
|
|
24
|
+
}
|
|
25
|
+
return redisManager.getConnectionForBullMQ()
|
|
26
|
+
}
|
package/src/redis/connection.ts
CHANGED
|
@@ -10,7 +10,7 @@ export interface RedisConnectionLogger {
|
|
|
10
10
|
error?: (message: string) => void
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
interface CreateRedisConnectionManagerOptions {
|
|
14
14
|
url: string
|
|
15
15
|
redisOptions?: RedisOptions
|
|
16
16
|
healthCheckIntervalMs?: number
|
package/src/redis/index.ts
CHANGED
|
@@ -1,30 +1,14 @@
|
|
|
1
|
-
import type IORedis from 'ioredis'
|
|
2
|
-
|
|
3
1
|
import { createRedisConnectionManager } from './connection'
|
|
4
2
|
import type { RedisConnectionManager } from './connection'
|
|
3
|
+
export { DEFAULT_REDIS_OPTIONS, type RedisConnectionLogger } from './connection'
|
|
4
|
+
export {
|
|
5
|
+
getRedisConnection,
|
|
6
|
+
getRedisConnectionForBullMQ,
|
|
7
|
+
setRedisConnectionManager,
|
|
8
|
+
type RedisConnectionAccessor,
|
|
9
|
+
} from './connection-accessor'
|
|
10
|
+
export { withOrgMemoryLock } from './org-memory-lock'
|
|
11
|
+
export { createWorkstreamResumableContext } from './stream-context'
|
|
5
12
|
|
|
6
13
|
export { createRedisConnectionManager }
|
|
7
14
|
export type { RedisConnectionManager }
|
|
8
|
-
|
|
9
|
-
let _redisManager: { getConnection(): IORedis; getConnectionForBullMQ(): IORedis } | undefined
|
|
10
|
-
|
|
11
|
-
export function setRedisConnectionManager(manager: {
|
|
12
|
-
getConnection(): IORedis
|
|
13
|
-
getConnectionForBullMQ(): IORedis
|
|
14
|
-
}): void {
|
|
15
|
-
_redisManager = manager
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export function getRedisConnection(): IORedis {
|
|
19
|
-
if (!_redisManager) {
|
|
20
|
-
throw new Error('Redis connection manager not configured. Call setRedisConnectionManager() first.')
|
|
21
|
-
}
|
|
22
|
-
return _redisManager.getConnection()
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export function getRedisConnectionForBullMQ(): IORedis {
|
|
26
|
-
if (!_redisManager) {
|
|
27
|
-
throw new Error('Redis connection manager not configured. Call setRedisConnectionManager() first.')
|
|
28
|
-
}
|
|
29
|
-
return _redisManager.getConnectionForBullMQ()
|
|
30
|
-
}
|
|
@@ -2,7 +2,7 @@ import type { Redis } from 'ioredis'
|
|
|
2
2
|
import type { Publisher, Subscriber } from 'resumable-stream/ioredis'
|
|
3
3
|
import { createResumableStreamContext } from 'resumable-stream/ioredis'
|
|
4
4
|
|
|
5
|
-
import { getRedisConnection } from './
|
|
5
|
+
import { getRedisConnection } from './connection-accessor'
|
|
6
6
|
|
|
7
7
|
function toSubscriber(client: Redis): Subscriber {
|
|
8
8
|
const handlers = new Map<string, (message: string) => void>()
|
|
@@ -34,11 +34,21 @@ function toPublisher(client: Redis): Publisher {
|
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
let sharedSubscriber: { client: Redis; subscriber: Subscriber } | undefined
|
|
38
|
+
|
|
39
|
+
function getSharedSubscriber(): Subscriber {
|
|
40
|
+
if (!sharedSubscriber) {
|
|
41
|
+
const client = getRedisConnection().duplicate()
|
|
42
|
+
sharedSubscriber = { client, subscriber: toSubscriber(client) }
|
|
43
|
+
}
|
|
44
|
+
return sharedSubscriber.subscriber
|
|
45
|
+
}
|
|
46
|
+
|
|
37
47
|
export function createWorkstreamResumableContext() {
|
|
38
48
|
const redis = getRedisConnection()
|
|
39
49
|
return createResumableStreamContext({
|
|
40
50
|
waitUntil: null,
|
|
41
|
-
subscriber:
|
|
51
|
+
subscriber: getSharedSubscriber(),
|
|
42
52
|
publisher: toPublisher(redis),
|
|
43
53
|
})
|
|
44
54
|
}
|