@lota-sdk/core 0.1.5

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 (153) hide show
  1. package/infrastructure/schema/00_workstream.surql +55 -0
  2. package/infrastructure/schema/01_memory.surql +47 -0
  3. package/infrastructure/schema/02_execution_plan.surql +62 -0
  4. package/infrastructure/schema/03_learned_skill.surql +32 -0
  5. package/infrastructure/schema/04_runtime_bootstrap.surql +8 -0
  6. package/package.json +128 -0
  7. package/src/ai/definitions.ts +308 -0
  8. package/src/bifrost/bifrost.ts +256 -0
  9. package/src/config/agent-defaults.ts +99 -0
  10. package/src/config/constants.ts +33 -0
  11. package/src/config/env-shapes.ts +122 -0
  12. package/src/config/logger.ts +29 -0
  13. package/src/config/model-constants.ts +31 -0
  14. package/src/config/search.ts +17 -0
  15. package/src/config/workstream-defaults.ts +68 -0
  16. package/src/db/base.service.ts +55 -0
  17. package/src/db/cursor-pagination.ts +73 -0
  18. package/src/db/memory-query-builder.ts +207 -0
  19. package/src/db/memory-store.helpers.ts +118 -0
  20. package/src/db/memory-store.rows.ts +29 -0
  21. package/src/db/memory-store.ts +974 -0
  22. package/src/db/memory-types.ts +193 -0
  23. package/src/db/memory.ts +505 -0
  24. package/src/db/record-id.ts +78 -0
  25. package/src/db/service.ts +932 -0
  26. package/src/db/startup.ts +152 -0
  27. package/src/db/tables.ts +20 -0
  28. package/src/document/org-document-chunking.ts +224 -0
  29. package/src/document/parsing.ts +40 -0
  30. package/src/embeddings/provider.ts +76 -0
  31. package/src/index.ts +302 -0
  32. package/src/queues/context-compaction.queue.ts +82 -0
  33. package/src/queues/document-processor.queue.ts +118 -0
  34. package/src/queues/memory-consolidation.queue.ts +65 -0
  35. package/src/queues/post-chat-memory.queue.ts +128 -0
  36. package/src/queues/recent-activity-title-refinement.queue.ts +69 -0
  37. package/src/queues/regular-chat-memory-digest.config.ts +12 -0
  38. package/src/queues/regular-chat-memory-digest.queue.ts +73 -0
  39. package/src/queues/skill-extraction.config.ts +9 -0
  40. package/src/queues/skill-extraction.queue.ts +62 -0
  41. package/src/redis/connection.ts +176 -0
  42. package/src/redis/index.ts +30 -0
  43. package/src/redis/org-memory-lock.ts +43 -0
  44. package/src/redis/redis-lease-lock.ts +158 -0
  45. package/src/runtime/agent-contract.ts +1 -0
  46. package/src/runtime/agent-prompt-context.ts +119 -0
  47. package/src/runtime/agent-runtime-policy.ts +192 -0
  48. package/src/runtime/agent-stream-helpers.ts +117 -0
  49. package/src/runtime/agent-types.ts +22 -0
  50. package/src/runtime/approval-continuation.ts +16 -0
  51. package/src/runtime/chat-attachments.ts +46 -0
  52. package/src/runtime/chat-message.ts +10 -0
  53. package/src/runtime/chat-request-routing.ts +21 -0
  54. package/src/runtime/chat-run-orchestration.ts +25 -0
  55. package/src/runtime/chat-run-registry.ts +20 -0
  56. package/src/runtime/chat-types.ts +18 -0
  57. package/src/runtime/context-compaction-constants.ts +11 -0
  58. package/src/runtime/context-compaction-runtime.ts +86 -0
  59. package/src/runtime/context-compaction.ts +909 -0
  60. package/src/runtime/execution-plan.ts +59 -0
  61. package/src/runtime/helper-model.ts +405 -0
  62. package/src/runtime/indexed-repositories-policy.ts +28 -0
  63. package/src/runtime/instruction-sections.ts +8 -0
  64. package/src/runtime/llm-content.ts +71 -0
  65. package/src/runtime/memory-block.ts +264 -0
  66. package/src/runtime/memory-digest-policy.ts +14 -0
  67. package/src/runtime/memory-format.ts +8 -0
  68. package/src/runtime/memory-pipeline.ts +570 -0
  69. package/src/runtime/memory-prompts-fact.ts +47 -0
  70. package/src/runtime/memory-prompts-parse.ts +3 -0
  71. package/src/runtime/memory-prompts-update.ts +37 -0
  72. package/src/runtime/memory-scope.ts +43 -0
  73. package/src/runtime/plugin-types.ts +10 -0
  74. package/src/runtime/retrieval-adapters.ts +25 -0
  75. package/src/runtime/retrieval-pipeline.ts +3 -0
  76. package/src/runtime/runtime-extensions.ts +154 -0
  77. package/src/runtime/skill-extraction-policy.ts +3 -0
  78. package/src/runtime/team-consultation-orchestrator.ts +245 -0
  79. package/src/runtime/team-consultation-prompts.ts +32 -0
  80. package/src/runtime/title-helpers.ts +12 -0
  81. package/src/runtime/turn-lifecycle.ts +28 -0
  82. package/src/runtime/workstream-chat-helpers.ts +187 -0
  83. package/src/runtime/workstream-routing-policy.ts +301 -0
  84. package/src/runtime/workstream-state.ts +261 -0
  85. package/src/services/attachment.service.ts +159 -0
  86. package/src/services/chat-attachments.service.ts +17 -0
  87. package/src/services/chat-run-registry.service.ts +3 -0
  88. package/src/services/context-compaction-runtime.ts +13 -0
  89. package/src/services/context-compaction.service.ts +115 -0
  90. package/src/services/document-chunk.service.ts +141 -0
  91. package/src/services/execution-plan.service.ts +890 -0
  92. package/src/services/learned-skill.service.ts +328 -0
  93. package/src/services/memory-assessment.service.ts +43 -0
  94. package/src/services/memory.service.ts +807 -0
  95. package/src/services/memory.utils.ts +84 -0
  96. package/src/services/mutating-approval.service.ts +110 -0
  97. package/src/services/recent-activity-title.service.ts +74 -0
  98. package/src/services/recent-activity.service.ts +397 -0
  99. package/src/services/workstream-change-tracker.service.ts +313 -0
  100. package/src/services/workstream-message.service.ts +283 -0
  101. package/src/services/workstream-title.service.ts +58 -0
  102. package/src/services/workstream-turn-preparation.ts +1340 -0
  103. package/src/services/workstream-turn.ts +37 -0
  104. package/src/services/workstream.service.ts +854 -0
  105. package/src/services/workstream.types.ts +118 -0
  106. package/src/storage/attachment-parser.ts +101 -0
  107. package/src/storage/attachment-storage.service.ts +391 -0
  108. package/src/storage/attachments.types.ts +11 -0
  109. package/src/storage/attachments.utils.ts +58 -0
  110. package/src/storage/generated-document-storage.service.ts +55 -0
  111. package/src/system-agents/agent-result.ts +27 -0
  112. package/src/system-agents/context-compacter.agent.ts +46 -0
  113. package/src/system-agents/delegated-agent-factory.ts +177 -0
  114. package/src/system-agents/helper-agent-options.ts +20 -0
  115. package/src/system-agents/memory-reranker.agent.ts +38 -0
  116. package/src/system-agents/memory.agent.ts +58 -0
  117. package/src/system-agents/recent-activity-title-refiner.agent.ts +53 -0
  118. package/src/system-agents/regular-chat-memory-digest.agent.ts +75 -0
  119. package/src/system-agents/researcher.agent.ts +34 -0
  120. package/src/system-agents/skill-extractor.agent.ts +88 -0
  121. package/src/system-agents/skill-manager.agent.ts +80 -0
  122. package/src/system-agents/title-generator.agent.ts +42 -0
  123. package/src/system-agents/workstream-tracker.agent.ts +58 -0
  124. package/src/tools/execution-plan.tool.ts +163 -0
  125. package/src/tools/fetch-webpage.tool.ts +132 -0
  126. package/src/tools/firecrawl-client.ts +12 -0
  127. package/src/tools/memory-block.tool.ts +55 -0
  128. package/src/tools/read-file-parts.tool.ts +80 -0
  129. package/src/tools/remember-memory.tool.ts +85 -0
  130. package/src/tools/research-topic.tool.ts +15 -0
  131. package/src/tools/search-tools.ts +55 -0
  132. package/src/tools/search-web.tool.ts +175 -0
  133. package/src/tools/team-think.tool.ts +125 -0
  134. package/src/tools/tool-contract.ts +21 -0
  135. package/src/tools/user-questions.tool.ts +18 -0
  136. package/src/utils/async.ts +50 -0
  137. package/src/utils/date-time.ts +34 -0
  138. package/src/utils/error.ts +10 -0
  139. package/src/utils/errors.ts +28 -0
  140. package/src/utils/hono-error-handler.ts +71 -0
  141. package/src/utils/string.ts +51 -0
  142. package/src/workers/bootstrap.ts +44 -0
  143. package/src/workers/memory-consolidation.worker.ts +318 -0
  144. package/src/workers/regular-chat-memory-digest.helpers.ts +100 -0
  145. package/src/workers/regular-chat-memory-digest.runner.ts +363 -0
  146. package/src/workers/regular-chat-memory-digest.worker.ts +22 -0
  147. package/src/workers/skill-extraction.runner.ts +331 -0
  148. package/src/workers/skill-extraction.worker.ts +22 -0
  149. package/src/workers/utils/repo-indexer-chunker.ts +331 -0
  150. package/src/workers/utils/repo-structure-extractor.ts +645 -0
  151. package/src/workers/utils/repomix-process-concurrency.ts +65 -0
  152. package/src/workers/utils/sandbox-error.ts +5 -0
  153. package/src/workers/worker-utils.ts +182 -0
@@ -0,0 +1,264 @@
1
+ import { agentDisplayNames, agentShortDisplayNames, resolveAgentNameAlias } from '../config/agent-defaults'
2
+
3
+ function escapeRegex(value: string): string {
4
+ return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
5
+ }
6
+
7
+ function normalizeMemoryBlockRole(role: string): string {
8
+ const canonicalRole = resolveAgentNameAlias(role)
9
+ if (canonicalRole) return canonicalRole
10
+ return role.trim().toLowerCase()
11
+ }
12
+
13
+ function getMemoryBlockRoleAliases(role: string): string[] {
14
+ const normalizedRole = role.trim()
15
+ if (!normalizedRole) return []
16
+
17
+ const canonicalRole = resolveAgentNameAlias(normalizedRole)
18
+ if (!canonicalRole) return [normalizedRole]
19
+
20
+ return [
21
+ normalizedRole,
22
+ canonicalRole,
23
+ agentDisplayNames[canonicalRole],
24
+ agentShortDisplayNames[canonicalRole],
25
+ ].filter((value): value is string => typeof value === 'string' && value.trim().length > 0)
26
+ }
27
+
28
+ function createLabelPrefixRegex(labelRoles: readonly string[]): RegExp | null {
29
+ if (labelRoles.length === 0) return null
30
+ const aliases = [...new Set(labelRoles.flatMap((role) => getMemoryBlockRoleAliases(role)))]
31
+ if (aliases.length === 0) return null
32
+ return new RegExp(`^(?:${aliases.map((role) => escapeRegex(role)).join('|')})\\s*:\\s*`, 'i')
33
+ }
34
+
35
+ export interface MemoryBlockEntry {
36
+ role: string
37
+ content: string
38
+ timestamp: string
39
+ }
40
+
41
+ export interface MemoryBlockRuntime {
42
+ normalizeMemoryBlockEntry: (entry: string) => string
43
+ validateMemoryBlockEntry: (entry: string) => { ok: boolean; reason?: string }
44
+ hasMemoryBlockEntry: (raw: string | null | undefined, role: string, entry: string) => boolean
45
+ parseMemoryBlock: (raw: string | null | undefined) => MemoryBlockEntry[]
46
+ serializeMemoryBlock: (entries: MemoryBlockEntry[]) => string
47
+ formatMemoryBlockForPrompt: (entries: MemoryBlockEntry[]) => string
48
+ appendToMemoryBlock: (entries: MemoryBlockEntry[], role: string, content: string) => MemoryBlockEntry[]
49
+ }
50
+
51
+ export interface PersistedMemoryBlockPromptParams {
52
+ summary?: string | null
53
+ entries: MemoryBlockEntry[]
54
+ }
55
+
56
+ export interface CompactMemoryBlockEntriesParams {
57
+ previousSummary?: string | null
58
+ entries: MemoryBlockEntry[]
59
+ triggerEntries: number
60
+ chunkEntries: number
61
+ compact: (params: { previousSummary: string; newEntriesText: string }) => Promise<string>
62
+ }
63
+
64
+ export interface CompactMemoryBlockEntriesResult {
65
+ compacted: boolean
66
+ summary: string
67
+ entries: MemoryBlockEntry[]
68
+ }
69
+
70
+ export interface PrepareMemoryBlockAppendParams {
71
+ entry: string
72
+ agentLabel: string
73
+ currentBlock?: string
74
+ normalizeEntry: (entry: string) => string
75
+ validateEntry: (entry: string) => { ok: boolean; reason?: string }
76
+ hasEntry: (raw: string | null | undefined, role: string, entry: string) => boolean
77
+ }
78
+
79
+ export type PrepareMemoryBlockAppendResult =
80
+ | { skipped: true; reason: string }
81
+ | { skipped: false; appendedBy: string; normalized: string; formatted: string; optimisticBlock: string }
82
+
83
+ export function formatPersistedMemoryBlockForPrompt(params: PersistedMemoryBlockPromptParams): string {
84
+ const sections: string[] = []
85
+ const summary = params.summary?.trim()
86
+ if (summary) {
87
+ sections.push(`summary: ${summary}`)
88
+ }
89
+
90
+ const entriesText =
91
+ params.entries.length === 0 ? '' : params.entries.map((entry) => `${entry.role}: ${entry.content}`).join('\n\n')
92
+
93
+ if (entriesText) {
94
+ sections.push(entriesText)
95
+ }
96
+
97
+ return sections.join('\n\n')
98
+ }
99
+
100
+ function toMemoryBlockEntriesSource(entries: Array<{ role: string; content: string }>): string {
101
+ return entries.map((entry) => `${entry.role}: ${entry.content}`).join('\n')
102
+ }
103
+
104
+ export async function compactMemoryBlockEntries(
105
+ params: CompactMemoryBlockEntriesParams,
106
+ ): Promise<CompactMemoryBlockEntriesResult> {
107
+ let summary = typeof params.previousSummary === 'string' ? params.previousSummary.trim() : ''
108
+ let entries = [...params.entries]
109
+ let compacted = false
110
+
111
+ while (entries.length >= params.triggerEntries) {
112
+ const chunk = entries.slice(0, params.chunkEntries)
113
+ const nextSummary = (
114
+ await params.compact({ previousSummary: summary, newEntriesText: toMemoryBlockEntriesSource(chunk) })
115
+ ).trim()
116
+
117
+ if (!nextSummary) {
118
+ break
119
+ }
120
+
121
+ summary = nextSummary
122
+ entries = entries.slice(params.chunkEntries)
123
+ compacted = true
124
+ }
125
+
126
+ return { compacted, summary, entries }
127
+ }
128
+
129
+ export function prepareMemoryBlockAppend(params: PrepareMemoryBlockAppendParams): PrepareMemoryBlockAppendResult {
130
+ const normalized = params.normalizeEntry(params.entry)
131
+ if (!normalized) {
132
+ return { skipped: true, reason: 'Empty memory block entry.' }
133
+ }
134
+
135
+ const validation = params.validateEntry(normalized)
136
+ if (!validation.ok) {
137
+ return { skipped: true, reason: `Invalid memory block entry: ${validation.reason}.` }
138
+ }
139
+
140
+ const label = normalizeMemoryBlockRole(params.agentLabel)
141
+ const formatted = `${label}: ${normalized}`
142
+ const currentBlock = params.currentBlock ?? ''
143
+ if (params.hasEntry(currentBlock, label, normalized) || (currentBlock && currentBlock.includes(formatted))) {
144
+ return { skipped: true, reason: 'Duplicate memory block entry.' }
145
+ }
146
+
147
+ const optimisticBlock = currentBlock.trim().length > 0 ? `${currentBlock.trim()}\n\n${formatted}` : formatted
148
+ return { skipped: false, appendedBy: label, normalized, formatted, optimisticBlock }
149
+ }
150
+
151
+ export interface CreateMemoryBlockRuntimeOptions {
152
+ labelRoles?: readonly string[]
153
+ maxChars?: number
154
+ now?: () => Date
155
+ }
156
+
157
+ export function createMemoryBlockRuntime(options: CreateMemoryBlockRuntimeOptions = {}): MemoryBlockRuntime {
158
+ const labelPrefixRegex = createLabelPrefixRegex(options.labelRoles ?? [])
159
+ const memoryBlockMaxChars = options.maxChars ?? 400
160
+ const now = options.now ?? (() => new Date())
161
+
162
+ const normalizeMemoryBlockEntry = (entry: string): string => {
163
+ const normalizedLines = entry
164
+ .replace(/\r\n/g, '\n')
165
+ .split('\n')
166
+ .map((line) => line.trim())
167
+ .filter(Boolean)
168
+ .map((line) =>
169
+ line
170
+ .replace(labelPrefixRegex ?? /^$/, '')
171
+ .replace(/^[-*]\s+/, '')
172
+ .trim(),
173
+ )
174
+ .filter(Boolean)
175
+
176
+ const candidate = normalizedLines.join(' ').trim()
177
+ const collapsed = candidate.replace(/\s+/g, ' ').trim()
178
+ if (!collapsed) return ''
179
+ return collapsed
180
+ }
181
+
182
+ const parseMemoryBlock = (raw: string | null | undefined): MemoryBlockEntry[] => {
183
+ if (!raw || !raw.trim()) return []
184
+ const trimmed = raw.trim()
185
+ if (!trimmed.startsWith('[')) return []
186
+ try {
187
+ const parsed: unknown = JSON.parse(trimmed)
188
+ if (!Array.isArray(parsed)) return []
189
+ return parsed as MemoryBlockEntry[]
190
+ } catch {
191
+ return []
192
+ }
193
+ }
194
+
195
+ const hasMemoryBlockEntry = (raw: string | null | undefined, role: string, entry: string): boolean => {
196
+ const normalizedTarget = normalizeMemoryBlockEntry(entry)
197
+ if (!normalizedTarget) return false
198
+ const roleLower = normalizeMemoryBlockRole(role)
199
+ if (!raw || !raw.trim()) return false
200
+
201
+ const parsed = parseMemoryBlock(raw)
202
+ if (parsed.length > 0) {
203
+ return parsed.some((item) => {
204
+ if (normalizeMemoryBlockRole(item.role) !== roleLower) return false
205
+ return normalizeMemoryBlockEntry(item.content) === normalizedTarget
206
+ })
207
+ }
208
+
209
+ return raw
210
+ .split('\n')
211
+ .map((line) => line.trim())
212
+ .filter(Boolean)
213
+ .some((line) => {
214
+ const match = line.match(/^([a-z][a-z0-9_ -]*)\s*:\s*(.+)$/i)
215
+ if (!match) return false
216
+ const rowRole = normalizeMemoryBlockRole(match[1] ?? '')
217
+ const rowContent = match[2] ?? ''
218
+ if (rowRole !== roleLower) return false
219
+ return normalizeMemoryBlockEntry(rowContent) === normalizedTarget
220
+ })
221
+ }
222
+
223
+ const validateMemoryBlockEntry = (entry: string): { ok: boolean; reason?: string } => {
224
+ const normalized = normalizeMemoryBlockEntry(entry)
225
+ if (!normalized) {
226
+ return { ok: false, reason: 'entry is empty after normalization' }
227
+ }
228
+
229
+ if (normalized.length > memoryBlockMaxChars) {
230
+ return { ok: false, reason: `entry exceeds ${memoryBlockMaxChars} characters` }
231
+ }
232
+
233
+ return { ok: true }
234
+ }
235
+
236
+ const serializeMemoryBlock = (entries: MemoryBlockEntry[]): string => JSON.stringify(entries)
237
+
238
+ const formatMemoryBlockForPrompt = (entries: MemoryBlockEntry[]): string => {
239
+ if (entries.length === 0) return ''
240
+ return entries.map((entry) => `${entry.role}: ${entry.content}`).join('\n\n')
241
+ }
242
+
243
+ const appendToMemoryBlock = (entries: MemoryBlockEntry[], role: string, content: string): MemoryBlockEntry[] => {
244
+ return [...entries, { role, content, timestamp: now().toISOString() }]
245
+ }
246
+
247
+ return {
248
+ normalizeMemoryBlockEntry,
249
+ validateMemoryBlockEntry,
250
+ hasMemoryBlockEntry,
251
+ parseMemoryBlock,
252
+ serializeMemoryBlock,
253
+ formatMemoryBlockForPrompt,
254
+ appendToMemoryBlock,
255
+ }
256
+ }
257
+
258
+ const _defaultRuntime = createMemoryBlockRuntime()
259
+ export const parseMemoryBlock = _defaultRuntime.parseMemoryBlock
260
+ export const serializeMemoryBlock = _defaultRuntime.serializeMemoryBlock
261
+ export const appendToMemoryBlock = _defaultRuntime.appendToMemoryBlock
262
+ export const hasMemoryBlockEntry = _defaultRuntime.hasMemoryBlockEntry
263
+ export const normalizeMemoryBlockEntry = _defaultRuntime.normalizeMemoryBlockEntry
264
+ export const validateMemoryBlockEntry = _defaultRuntime.validateMemoryBlockEntry
@@ -0,0 +1,14 @@
1
+ export function shouldEnqueueOnboardingPostChatMemory(params: {
2
+ onboardingActive: boolean
3
+ userMessageText: string
4
+ hasAttachmentContext: boolean
5
+ agentMessageCount: number
6
+ }): boolean {
7
+ if (!params.onboardingActive) return false
8
+ if (params.agentMessageCount <= 0) return false
9
+ return params.userMessageText.trim().length > 0 || params.hasAttachmentContext
10
+ }
11
+
12
+ export function shouldEnqueueRegularDigestForWorkstream(params: { onboardingActive: boolean }): boolean {
13
+ return !params.onboardingActive
14
+ }
@@ -0,0 +1,8 @@
1
+ interface MemorySearchResultLike {
2
+ content: string
3
+ }
4
+
5
+ export function formatResults<T extends MemorySearchResultLike>(results: T[]): string {
6
+ if (results.length === 0) return 'No stored memories.'
7
+ return results.map((item) => `- ${item.content}`).join('\n')
8
+ }