@lota-sdk/core 0.4.9 → 0.4.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/src/ai/embedding-cache.ts +3 -1
- package/src/ai-gateway/ai-gateway.ts +164 -82
- package/src/ai-gateway/index.ts +16 -1
- package/src/config/agent-defaults.ts +4 -107
- package/src/config/agent-types.ts +1 -1
- package/src/config/background-processing.ts +1 -1
- package/src/config/index.ts +0 -1
- package/src/config/logger.ts +22 -25
- package/src/config/thread-defaults.ts +1 -10
- package/src/create-runtime.ts +145 -670
- package/src/db/base.service.ts +30 -38
- package/src/db/memory-query-builder.ts +2 -1
- package/src/db/memory-store.ts +29 -20
- package/src/db/memory.ts +188 -195
- package/src/db/service-normalization.ts +97 -64
- package/src/db/service.ts +496 -384
- package/src/db/startup.ts +30 -19
- package/src/effect/helpers.ts +30 -5
- package/src/effect/index.ts +7 -7
- package/src/effect/layers.ts +75 -72
- package/src/effect/services.ts +15 -11
- package/src/embeddings/provider.ts +65 -71
- package/src/index.ts +13 -12
- package/src/queues/autonomous-job.queue.ts +177 -143
- package/src/queues/context-compaction.queue.ts +41 -39
- package/src/queues/delayed-node-promotion.queue.ts +61 -42
- package/src/queues/document-processor.queue.ts +5 -3
- package/src/queues/index.ts +1 -0
- package/src/queues/memory-consolidation.queue.ts +79 -53
- package/src/queues/organization-learning.queue.ts +70 -33
- package/src/queues/plan-agent-heartbeat.queue.ts +111 -83
- package/src/queues/plan-scheduler.queue.ts +101 -97
- package/src/queues/post-chat-memory.queue.ts +56 -46
- package/src/queues/queue-factory.ts +146 -69
- package/src/queues/queues.service.ts +61 -0
- package/src/queues/title-generation.queue.ts +44 -44
- package/src/redis/connection.ts +181 -164
- package/src/redis/org-memory-lock.ts +24 -9
- package/src/redis/redis-lease-lock.ts +8 -1
- package/src/redis/stream-context.ts +17 -9
- package/src/runtime/agent-identity-overrides.ts +7 -3
- package/src/runtime/agent-runtime-policy.ts +10 -5
- package/src/runtime/agent-stream-helpers.ts +24 -15
- package/src/runtime/chat-run-orchestration.ts +1 -1
- package/src/runtime/context-compaction/context-compaction-runtime.ts +28 -32
- package/src/runtime/context-compaction/context-compaction.ts +131 -85
- package/src/runtime/domain-layer.ts +203 -0
- package/src/runtime/execution-plan-visibility.ts +5 -2
- package/src/runtime/graph-designer.ts +0 -14
- package/src/runtime/helper-model.ts +8 -4
- package/src/runtime/index.ts +1 -1
- package/src/runtime/indexed-repositories-policy.ts +2 -6
- package/src/runtime/memory/memory-block.ts +19 -9
- package/src/runtime/memory/memory-pipeline.ts +53 -66
- package/src/runtime/memory/memory-scope.ts +33 -29
- package/src/runtime/plugin-resolution.ts +58 -62
- package/src/runtime/post-turn-side-effects.ts +139 -161
- package/src/runtime/retrieval-adapters.ts +4 -4
- package/src/runtime/runtime-config.ts +3 -9
- package/src/runtime/runtime-extensions.ts +0 -43
- package/src/runtime/runtime-lifecycle.ts +124 -0
- package/src/runtime/runtime-services.ts +455 -0
- package/src/runtime/runtime-worker-registry.ts +113 -30
- package/src/runtime/social-chat/social-chat-agent-runner.ts +13 -8
- package/src/runtime/social-chat/social-chat-history.ts +24 -13
- package/src/runtime/social-chat/social-chat.ts +420 -369
- package/src/runtime/team-consultation/team-consultation-orchestrator.ts +64 -57
- package/src/runtime/team-consultation/team-consultation-prompts.ts +11 -6
- package/src/runtime/thread-chat-helpers.ts +18 -9
- package/src/runtime/thread-turn-context.ts +28 -74
- package/src/runtime/turn-lifecycle.ts +6 -14
- package/src/services/agent-activity.service.ts +169 -176
- package/src/services/agent-executor.service.ts +207 -196
- package/src/services/artifact.service.ts +10 -5
- package/src/services/attachment.service.ts +16 -48
- package/src/services/autonomous-job.service.ts +81 -87
- package/src/services/background-work.service.ts +54 -0
- package/src/services/chat-run-registry.service.ts +3 -1
- package/src/services/context-compaction.service.ts +8 -10
- package/src/services/document-chunk.service.ts +8 -17
- package/src/services/execution-plan/execution-plan-graph.ts +122 -109
- package/src/services/execution-plan/execution-plan-schedule.ts +1 -15
- package/src/services/execution-plan/execution-plan.service.ts +68 -51
- package/src/services/feedback-loop.service.ts +1 -1
- package/src/services/global-orchestrator.service.ts +49 -15
- package/src/services/graph-full-routing.ts +49 -37
- package/src/services/index.ts +1 -0
- package/src/services/institutional-memory.service.ts +8 -17
- package/src/services/learned-skill.service.ts +38 -35
- package/src/services/memory/memory-conversation.ts +10 -5
- package/src/services/memory/memory-errors.ts +27 -0
- package/src/services/memory/memory-org-memory.ts +14 -3
- package/src/services/memory/memory-preseeded.ts +10 -4
- package/src/services/memory/memory-utils.ts +2 -1
- package/src/services/memory/memory.service.ts +37 -52
- package/src/services/memory/rerank.service.ts +3 -11
- package/src/services/monitoring-window.service.ts +1 -1
- package/src/services/mutating-approval.service.ts +1 -1
- package/src/services/node-workspace.service.ts +2 -2
- package/src/services/notification.service.ts +16 -4
- package/src/services/organization-member.service.ts +1 -1
- package/src/services/organization.service.ts +34 -51
- package/src/services/ownership-dispatcher.service.ts +148 -95
- package/src/services/plan/plan-agent-heartbeat.service.ts +30 -16
- package/src/services/plan/plan-agent-query.service.ts +13 -9
- package/src/services/plan/plan-approval.service.ts +52 -48
- package/src/services/plan/plan-artifact.service.ts +2 -2
- package/src/services/plan/plan-builder.service.ts +2 -2
- package/src/services/plan/plan-checkpoint.service.ts +1 -1
- package/src/services/plan/plan-compiler.service.ts +1 -1
- package/src/services/plan/plan-completion-side-effects.ts +99 -113
- package/src/services/plan/plan-coordination.service.ts +1 -1
- package/src/services/plan/plan-cycle.service.ts +171 -202
- package/src/services/plan/plan-deadline.service.ts +304 -307
- package/src/services/plan/plan-event-delivery.service.ts +84 -72
- package/src/services/plan/plan-executor-context.ts +2 -0
- package/src/services/plan/plan-executor-graph.ts +375 -353
- package/src/services/plan/plan-executor-helpers.ts +60 -75
- package/src/services/plan/plan-executor.service.ts +494 -489
- package/src/services/plan/plan-run.service.ts +12 -19
- package/src/services/plan/plan-scheduler.service.ts +89 -82
- package/src/services/plan/plan-template.service.ts +1 -1
- package/src/services/plan/plan-transaction-events.ts +8 -5
- package/src/services/plan/plan-validator.service.ts +1 -1
- package/src/services/plan/plan-workspace.service.ts +17 -11
- package/src/services/plugin-executor.service.ts +26 -21
- package/src/services/quality-metrics.service.ts +1 -1
- package/src/services/queue-job.service.ts +8 -17
- package/src/services/recent-activity-title.service.ts +22 -10
- package/src/services/recent-activity.service.ts +1 -1
- package/src/services/skill-resolver.service.ts +1 -1
- package/src/services/social-chat-history.service.ts +37 -20
- package/src/services/system-executor.service.ts +25 -20
- package/src/services/thread/thread-bootstrap.ts +37 -19
- package/src/services/thread/thread-listing.ts +2 -1
- package/src/services/thread/thread-memory-block.ts +18 -5
- package/src/services/thread/thread-message.service.ts +30 -13
- package/src/services/thread/thread-title.service.ts +1 -1
- package/src/services/thread/thread-turn-execution.ts +87 -83
- package/src/services/thread/thread-turn-preparation.service.ts +65 -40
- package/src/services/thread/thread-turn-streaming.ts +32 -36
- package/src/services/thread/thread-turn.ts +43 -29
- package/src/services/thread/thread.service.ts +32 -8
- package/src/services/user.service.ts +1 -1
- package/src/services/write-intent-validator.service.ts +1 -1
- package/src/storage/attachment-storage.service.ts +7 -4
- package/src/storage/generated-document-storage.service.ts +1 -1
- package/src/system-agents/context-compaction.agent.ts +1 -1
- package/src/system-agents/helper-agent-options.ts +1 -1
- package/src/system-agents/memory-reranker.agent.ts +1 -1
- package/src/system-agents/memory.agent.ts +1 -1
- package/src/system-agents/recent-activity-title-refiner.agent.ts +9 -6
- 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 +1 -1
- package/src/system-agents/thread-router.agent.ts +23 -20
- package/src/system-agents/title-generator.agent.ts +1 -1
- package/src/tools/execution-plan.tool.ts +36 -20
- package/src/tools/fetch-webpage.tool.ts +30 -22
- package/src/tools/firecrawl-client.ts +1 -6
- package/src/tools/plan-approval.tool.ts +9 -1
- package/src/tools/remember-memory.tool.ts +3 -6
- package/src/tools/research-topic.tool.ts +12 -3
- package/src/tools/search-web.tool.ts +26 -18
- package/src/tools/search.tool.ts +4 -5
- package/src/tools/team-think.tool.ts +139 -121
- package/src/utils/async.ts +15 -6
- package/src/utils/errors.ts +27 -15
- package/src/workers/bootstrap.ts +34 -58
- package/src/workers/memory-consolidation.worker.ts +4 -1
- package/src/workers/organization-learning.worker.ts +16 -3
- package/src/workers/regular-chat-memory-digest.helpers.ts +3 -4
- package/src/workers/regular-chat-memory-digest.runner.ts +46 -29
- package/src/workers/skill-extraction.runner.ts +13 -15
- package/src/workers/worker-utils.ts +14 -8
- package/src/config/search.ts +0 -3
- package/src/effect/awaitable-effect.ts +0 -87
- package/src/effect/runtime-ref.ts +0 -25
- package/src/effect/runtime.ts +0 -31
- package/src/redis/runtime-connection.ts +0 -10
- package/src/runtime/agent-types.ts +0 -1
package/src/db/memory.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { Context } from 'effect'
|
|
2
|
+
import { Effect } from 'effect'
|
|
2
3
|
import type { z } from 'zod'
|
|
3
4
|
|
|
4
5
|
import { aiLogger } from '../config/logger'
|
|
@@ -15,6 +16,8 @@ import { getFactRetrievalMessages } from '../runtime/memory/memory-prompts-fact'
|
|
|
15
16
|
import { parseMessages } from '../runtime/memory/memory-prompts-parse'
|
|
16
17
|
import { getClassifyMemoryDeltaPrompt } from '../runtime/memory/memory-prompts-update'
|
|
17
18
|
import type { ResolvedLotaRuntimeConfig } from '../runtime/runtime-config'
|
|
19
|
+
import type { BackgroundWorkService } from '../services/background-work.service'
|
|
20
|
+
import { MemoryServiceError, tryMemoryPromise } from '../services/memory/memory-errors'
|
|
18
21
|
import { sha256Hex } from '../utils/crypto'
|
|
19
22
|
import { compactWhitespace, truncateText } from '../utils/string'
|
|
20
23
|
import type { SurrealMemoryStore } from './memory-store'
|
|
@@ -54,32 +57,6 @@ interface PreparedScopeUpdate {
|
|
|
54
57
|
existingMemories: Array<{ id: string; text: string }>
|
|
55
58
|
}
|
|
56
59
|
|
|
57
|
-
class MemoryServiceError extends Schema.TaggedErrorClass<MemoryServiceError>()('MemoryServiceError', {
|
|
58
|
-
message: Schema.String,
|
|
59
|
-
cause: Schema.Defect,
|
|
60
|
-
}) {}
|
|
61
|
-
|
|
62
|
-
function tryMemoryPromise<A, R = never>(
|
|
63
|
-
message: string,
|
|
64
|
-
thunk: () => PromiseLike<A> | Effect.Effect<A, unknown, R>,
|
|
65
|
-
): Effect.Effect<A, MemoryServiceError, R> {
|
|
66
|
-
return Effect.suspend(() => {
|
|
67
|
-
try {
|
|
68
|
-
const value = thunk()
|
|
69
|
-
if (Effect.isEffect(value)) {
|
|
70
|
-
return value.pipe(Effect.mapError((cause) => new MemoryServiceError({ message, cause })))
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
return Effect.tryPromise({
|
|
74
|
-
try: () => Promise.resolve(value),
|
|
75
|
-
catch: (cause) => new MemoryServiceError({ message, cause }),
|
|
76
|
-
})
|
|
77
|
-
} catch (cause) {
|
|
78
|
-
return Effect.fail(new MemoryServiceError({ message, cause }))
|
|
79
|
-
}
|
|
80
|
-
})
|
|
81
|
-
}
|
|
82
|
-
|
|
83
60
|
export class Memory {
|
|
84
61
|
private store: SurrealMemoryStore
|
|
85
62
|
private createAgent: CreateHelperAgentFn
|
|
@@ -89,14 +66,23 @@ export class Memory {
|
|
|
89
66
|
private helperModelRuntime: HelperModelRuntime
|
|
90
67
|
|
|
91
68
|
constructor(
|
|
92
|
-
deps: {
|
|
69
|
+
deps: {
|
|
70
|
+
db: SurrealDBService
|
|
71
|
+
runtimeConfig: ResolvedLotaRuntimeConfig
|
|
72
|
+
helperModelRuntime: HelperModelRuntime
|
|
73
|
+
background: Context.Service.Shape<typeof BackgroundWorkService>
|
|
74
|
+
},
|
|
93
75
|
agent: { createAgent: CreateHelperAgentFn; maxOutputTokens?: number },
|
|
94
76
|
config: MemoryConfig = {},
|
|
95
77
|
) {
|
|
96
|
-
this.store = createMemoryStore(
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
78
|
+
this.store = createMemoryStore(
|
|
79
|
+
deps.db,
|
|
80
|
+
{
|
|
81
|
+
embeddingModel: deps.runtimeConfig.aiGateway.embeddingModel,
|
|
82
|
+
openRouterApiKey: deps.runtimeConfig.aiGateway.openRouterApiKey,
|
|
83
|
+
},
|
|
84
|
+
deps.background,
|
|
85
|
+
)
|
|
100
86
|
this.runtimeConfig = deps.runtimeConfig
|
|
101
87
|
this.helperModelRuntime = deps.helperModelRuntime
|
|
102
88
|
this.createAgent = agent.createAgent
|
|
@@ -142,73 +128,77 @@ export class Memory {
|
|
|
142
128
|
}
|
|
143
129
|
|
|
144
130
|
search(query: string, options: SearchOptions): Effect.Effect<string, MemoryServiceError, never> {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
131
|
+
return Effect.gen(
|
|
132
|
+
function* (this: Memory) {
|
|
133
|
+
const limit = options.limit ?? this.runtimeConfig.memory.searchK
|
|
134
|
+
const results = yield* tryMemoryPromise('Failed to search memory.', () =>
|
|
135
|
+
this.store.search(query, options.scopeId, limit, options.memoryType),
|
|
136
|
+
)
|
|
137
|
+
return formatResults(results)
|
|
138
|
+
}.bind(this),
|
|
139
|
+
)
|
|
153
140
|
}
|
|
154
141
|
|
|
155
142
|
hybridSearch(query: string, options: SearchOptions): Effect.Effect<string, MemoryServiceError, never> {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
143
|
+
return Effect.gen(
|
|
144
|
+
function* (this: Memory) {
|
|
145
|
+
const limit = options.limit ?? this.runtimeConfig.memory.searchK
|
|
146
|
+
const results = yield* tryMemoryPromise('Failed to perform hybrid search.', () =>
|
|
147
|
+
this.store.hybridSearch(query, options.scopeId, limit, options.memoryType),
|
|
148
|
+
)
|
|
149
|
+
return formatResults(results)
|
|
150
|
+
}.bind(this),
|
|
151
|
+
)
|
|
164
152
|
}
|
|
165
153
|
|
|
166
154
|
hybridSearchWeighted(
|
|
167
155
|
query: string,
|
|
168
156
|
options: SearchOptions & { weights?: [number, number]; normalization?: 'minmax' | 'zscore' },
|
|
169
157
|
): Effect.Effect<string, MemoryServiceError, never> {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
158
|
+
return Effect.gen(
|
|
159
|
+
function* (this: Memory) {
|
|
160
|
+
const limit = options.limit ?? this.runtimeConfig.memory.searchK
|
|
161
|
+
const results = yield* tryMemoryPromise('Failed to perform weighted hybrid search.', () =>
|
|
162
|
+
this.store.hybridSearchWeighted(query, {
|
|
163
|
+
scopeId: options.scopeId,
|
|
164
|
+
limit,
|
|
165
|
+
memoryType: options.memoryType,
|
|
166
|
+
weights: options.weights,
|
|
167
|
+
normalization: options.normalization,
|
|
168
|
+
}),
|
|
169
|
+
)
|
|
170
|
+
return formatResults(results)
|
|
171
|
+
}.bind(this),
|
|
172
|
+
)
|
|
184
173
|
}
|
|
185
174
|
|
|
186
175
|
searchCandidates(
|
|
187
176
|
query: string,
|
|
188
177
|
options: WeightedSearchOptions,
|
|
189
178
|
): Effect.Effect<MemorySearchResult[], MemoryServiceError, never> {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
179
|
+
return Effect.gen(
|
|
180
|
+
function* (this: Memory) {
|
|
181
|
+
const limit = options.limit ?? this.runtimeConfig.memory.searchK
|
|
182
|
+
const results = yield* tryMemoryPromise('Failed to search memory candidates.', () =>
|
|
183
|
+
this.store.hybridSearchWeighted(query, {
|
|
184
|
+
scopeId: options.scopeId,
|
|
185
|
+
limit,
|
|
186
|
+
memoryType: options.memoryType,
|
|
187
|
+
weights: options.weights,
|
|
188
|
+
normalization: options.normalization,
|
|
189
|
+
fastMode: options.fastMode,
|
|
190
|
+
}),
|
|
191
|
+
)
|
|
203
192
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
193
|
+
if (options.fastMode || options.includeNeighborContext === false) {
|
|
194
|
+
return results
|
|
195
|
+
}
|
|
207
196
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
197
|
+
return yield* tryMemoryPromise('Failed to enrich memory candidates.', () =>
|
|
198
|
+
this.store.enrichWithNeighbors(results),
|
|
199
|
+
)
|
|
200
|
+
}.bind(this),
|
|
201
|
+
)
|
|
212
202
|
}
|
|
213
203
|
|
|
214
204
|
listTopMemories(options: {
|
|
@@ -248,28 +238,30 @@ export class Memory {
|
|
|
248
238
|
messages: Message[],
|
|
249
239
|
extractionOptions?: { customPrompt?: string; maxFacts?: number },
|
|
250
240
|
): Effect.Effect<ExtractedFact[], MemoryServiceError, never> {
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
const parsedMessages = parseMessages(messages)
|
|
256
|
-
const facts = yield* self.extractFactsEffect(parsedMessages, extractionOptions)
|
|
257
|
-
if (facts.length === 0) {
|
|
258
|
-
aiLogger.debug`No facts extracted from conversation`
|
|
259
|
-
return []
|
|
260
|
-
}
|
|
241
|
+
return Effect.gen(
|
|
242
|
+
function* (this: Memory) {
|
|
243
|
+
if (messages.length === 0) return []
|
|
261
244
|
|
|
262
|
-
|
|
263
|
-
|
|
245
|
+
const parsedMessages = parseMessages(messages)
|
|
246
|
+
const facts = yield* this.extractFactsEffect(parsedMessages, extractionOptions)
|
|
247
|
+
if (facts.length === 0) {
|
|
248
|
+
aiLogger.debug`No facts extracted from conversation`
|
|
249
|
+
return []
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
return facts
|
|
253
|
+
}.bind(this),
|
|
254
|
+
)
|
|
264
255
|
}
|
|
265
256
|
|
|
266
257
|
applyFactsToScopes(facts: ExtractedFact[], scopes: AddOptions[]): Effect.Effect<void, MemoryServiceError, never> {
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
258
|
+
return Effect.gen(
|
|
259
|
+
function* (this: Memory) {
|
|
260
|
+
if (facts.length === 0 || scopes.length === 0) return
|
|
261
|
+
const prepared = yield* this.prepareFactsToScopesEffect(facts, scopes)
|
|
262
|
+
yield* this.applyPreparedScopeUpdates(prepared)
|
|
263
|
+
}.bind(this),
|
|
264
|
+
)
|
|
273
265
|
}
|
|
274
266
|
|
|
275
267
|
prepareFactsToScopes(
|
|
@@ -551,105 +543,106 @@ export class Memory {
|
|
|
551
543
|
factMaps: ReturnType<typeof buildMemoryFactMaps>,
|
|
552
544
|
existingMemories: Array<{ id: string; text: string }>,
|
|
553
545
|
): Effect.Effect<void, MemoryServiceError, never> {
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
const idMap = new Map<string, string>()
|
|
568
|
-
for (const action of plan.actions) {
|
|
569
|
-
switch (action.type) {
|
|
570
|
-
case 'add': {
|
|
571
|
-
const truncatedContent = truncateText(action.text, 50)
|
|
572
|
-
const metadata = { ...options.metadata, memoryCategory: action.category }
|
|
573
|
-
const hash = hashContent(action.text, options.scopeId, options.memoryType)
|
|
574
|
-
|
|
575
|
-
const newId = yield* tryMemoryPromise(`Failed to insert memory for scope ${options.scopeId}.`, () =>
|
|
576
|
-
self.store.insert(
|
|
577
|
-
action.text,
|
|
578
|
-
options.scopeId,
|
|
579
|
-
options.memoryType,
|
|
580
|
-
metadata,
|
|
581
|
-
action.importance,
|
|
582
|
-
action.durability as Durability,
|
|
583
|
-
),
|
|
584
|
-
).pipe(
|
|
585
|
-
Effect.catchTag('MemoryServiceError', (error) => {
|
|
586
|
-
if (!isUniqueIndexConflict(error.cause, 'memoryHashIdx')) {
|
|
587
|
-
return Effect.fail(error)
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
return tryMemoryPromise(`Failed to look up memory hash ${hash}.`, () =>
|
|
591
|
-
self.store.getByHash(hash),
|
|
592
|
-
).pipe(
|
|
593
|
-
Effect.flatMap((existing) => {
|
|
594
|
-
if (!existing) {
|
|
595
|
-
return Effect.fail(error)
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
return Effect.sync(() => {
|
|
599
|
-
aiLogger.debug`Skipped duplicate memory insert due to hash conflict: ${existing.id}`
|
|
600
|
-
return existing.id
|
|
601
|
-
})
|
|
602
|
-
}),
|
|
603
|
-
)
|
|
604
|
-
}),
|
|
605
|
-
)
|
|
546
|
+
return Effect.gen(
|
|
547
|
+
function* (this: Memory) {
|
|
548
|
+
const plan = createMemoryActionPlan({
|
|
549
|
+
updates,
|
|
550
|
+
memoryType: options.memoryType,
|
|
551
|
+
explicitImportance: options.importance,
|
|
552
|
+
extractedImportanceByKey: factMaps.extractedImportanceByKey,
|
|
553
|
+
confidenceByKey: factMaps.confidenceByKey,
|
|
554
|
+
durabilityByKey: factMaps.durabilityByKey,
|
|
555
|
+
categoryByKey: factMaps.categoryByKey,
|
|
556
|
+
existingMemories,
|
|
557
|
+
})
|
|
606
558
|
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
559
|
+
const idMap = new Map<string, string>()
|
|
560
|
+
for (const action of plan.actions) {
|
|
561
|
+
switch (action.type) {
|
|
562
|
+
case 'add': {
|
|
563
|
+
const truncatedContent = truncateText(action.text, 50)
|
|
564
|
+
const metadata = { ...options.metadata, memoryCategory: action.category }
|
|
565
|
+
const hash = hashContent(action.text, options.scopeId, options.memoryType)
|
|
566
|
+
|
|
567
|
+
const newId = yield* tryMemoryPromise(`Failed to insert memory for scope ${options.scopeId}.`, () =>
|
|
568
|
+
this.store.insert(
|
|
569
|
+
action.text,
|
|
570
|
+
options.scopeId,
|
|
571
|
+
options.memoryType,
|
|
572
|
+
metadata,
|
|
573
|
+
action.importance,
|
|
574
|
+
action.durability as Durability,
|
|
575
|
+
),
|
|
576
|
+
).pipe(
|
|
577
|
+
Effect.catchTag('MemoryServiceError', (error) => {
|
|
578
|
+
if (!isUniqueIndexConflict(error.cause, 'memoryHashIdx')) {
|
|
579
|
+
return Effect.fail(error)
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
return tryMemoryPromise(`Failed to look up memory hash ${hash}.`, () =>
|
|
583
|
+
this.store.getByHash(hash),
|
|
584
|
+
).pipe(
|
|
585
|
+
Effect.flatMap((existing) => {
|
|
586
|
+
if (!existing) {
|
|
587
|
+
return Effect.fail(error)
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
return Effect.sync(() => {
|
|
591
|
+
aiLogger.debug`Skipped duplicate memory insert due to hash conflict: ${existing.id}`
|
|
592
|
+
return existing.id
|
|
593
|
+
})
|
|
594
|
+
}),
|
|
595
|
+
)
|
|
596
|
+
}),
|
|
597
|
+
)
|
|
598
|
+
|
|
599
|
+
idMap.set(action.refId, newId)
|
|
600
|
+
aiLogger.debug`Added new memory (memoryType: ${options.memoryType}, category: ${action.category}, durability: ${action.durability}, importance: ${action.importance.toFixed(2)}, content: ${truncatedContent})`
|
|
601
|
+
break
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
case 'update': {
|
|
605
|
+
const metadata = { ...options.metadata, ...(action.category ? { memoryCategory: action.category } : {}) }
|
|
606
|
+
yield* tryMemoryPromise(`Failed to update memory ${action.refId}.`, () =>
|
|
607
|
+
this.store.update(action.refId, action.text, {
|
|
608
|
+
importance: action.importance,
|
|
609
|
+
durability: action.durability as Durability | undefined,
|
|
610
|
+
metadata: Object.keys(metadata).length > 0 ? metadata : undefined,
|
|
611
|
+
}),
|
|
612
|
+
)
|
|
613
|
+
idMap.set(action.refId, action.refId)
|
|
614
|
+
aiLogger.debug`Updated memory ${action.refId}: ${truncateText(action.text, 50)}`
|
|
615
|
+
break
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
case 'delete':
|
|
619
|
+
yield* tryMemoryPromise(`Failed to delete memory ${action.refId}.`, () => this.store.delete(action.refId))
|
|
620
|
+
aiLogger.debug`Deleted memory ${action.refId}`
|
|
621
|
+
break
|
|
610
622
|
}
|
|
623
|
+
}
|
|
611
624
|
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
625
|
+
for (const relation of plan.relations) {
|
|
626
|
+
const fromId = idMap.get(relation.fromRefId)
|
|
627
|
+
if (!fromId) continue
|
|
628
|
+
|
|
629
|
+
const toId = idMap.get(relation.toRefId) ?? relation.toRefId
|
|
630
|
+
yield* tryMemoryPromise(`Failed to create memory relation ${relation.relation}.`, () =>
|
|
631
|
+
this.store.addRelation(fromId, toId, relation.relation),
|
|
632
|
+
).pipe(
|
|
633
|
+
Effect.tap(() =>
|
|
634
|
+
Effect.sync(() => {
|
|
635
|
+
aiLogger.debug`Created ${relation.relation} relation: ${fromId} -> ${toId}`
|
|
619
636
|
}),
|
|
620
|
-
)
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
yield* tryMemoryPromise(`Failed to delete memory ${action.refId}.`, () => self.store.delete(action.refId))
|
|
628
|
-
aiLogger.debug`Deleted memory ${action.refId}`
|
|
629
|
-
break
|
|
637
|
+
),
|
|
638
|
+
Effect.catchTag('MemoryServiceError', (error) =>
|
|
639
|
+
Effect.sync(() => {
|
|
640
|
+
aiLogger.warn`Failed to create memory relation (non-fatal, graph may be incomplete): ${error.message}`
|
|
641
|
+
}),
|
|
642
|
+
),
|
|
643
|
+
)
|
|
630
644
|
}
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
for (const relation of plan.relations) {
|
|
634
|
-
const fromId = idMap.get(relation.fromRefId)
|
|
635
|
-
if (!fromId) continue
|
|
636
|
-
|
|
637
|
-
const toId = idMap.get(relation.toRefId) ?? relation.toRefId
|
|
638
|
-
yield* tryMemoryPromise(`Failed to create memory relation ${relation.relation}.`, () =>
|
|
639
|
-
self.store.addRelation(fromId, toId, relation.relation),
|
|
640
|
-
).pipe(
|
|
641
|
-
Effect.tap(() =>
|
|
642
|
-
Effect.sync(() => {
|
|
643
|
-
aiLogger.debug`Created ${relation.relation} relation: ${fromId} -> ${toId}`
|
|
644
|
-
}),
|
|
645
|
-
),
|
|
646
|
-
Effect.catchTag('MemoryServiceError', (error) =>
|
|
647
|
-
Effect.sync(() => {
|
|
648
|
-
aiLogger.warn`Failed to create memory relation (non-fatal, graph may be incomplete): ${error.message}`
|
|
649
|
-
}),
|
|
650
|
-
),
|
|
651
|
-
)
|
|
652
|
-
}
|
|
653
|
-
})
|
|
645
|
+
}.bind(this),
|
|
646
|
+
)
|
|
654
647
|
}
|
|
655
648
|
}
|