@smyslenny/agent-memory 5.0.0 → 5.0.2
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/.github/workflows/test.yml +1 -1
- package/.pnpm-approve-builds.json +1 -0
- package/CHANGELOG.md +115 -0
- package/README.md +52 -15
- package/dist/bin/agent-memory.js +88 -16
- package/dist/bin/agent-memory.js.map +1 -1
- package/dist/index.d.ts +13 -1
- package/dist/index.js +93 -15
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.js +174 -13884
- package/dist/mcp/server.js.map +1 -1
- package/docs/README-zh.md +133 -15
- package/docs/architecture.md +1 -1
- package/docs/integrations/openclaw.md +1 -1
- package/package.json +4 -3
package/dist/index.d.ts
CHANGED
|
@@ -330,6 +330,16 @@ declare function fusionScore(input: {
|
|
|
330
330
|
recency_boost?: number;
|
|
331
331
|
}): number;
|
|
332
332
|
declare function fuseHybridResults(lexical: SearchResult[], vector: VectorSearchResult[], limit: number, recency_boost?: number): HybridRecallResult[];
|
|
333
|
+
interface RelatedLink {
|
|
334
|
+
memory: Memory;
|
|
335
|
+
sourceId: string;
|
|
336
|
+
weight: number;
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Fetch related memories from the links table for a set of source memory IDs.
|
|
340
|
+
* Shared by both recall and surface expansion paths.
|
|
341
|
+
*/
|
|
342
|
+
declare function fetchRelatedLinks(db: Database.Database, sourceIds: string[], agentId: string, excludeIds: Set<string>, maxPerSource?: number): RelatedLink[];
|
|
333
343
|
declare function recallMemories(db: Database.Database, query: string, opts?: RecallOptions): Promise<HybridRecallResponse>;
|
|
334
344
|
declare function reindexEmbeddings(db: Database.Database, opts?: ReindexOptions): Promise<ReindexEmbeddingsResult>;
|
|
335
345
|
declare function reindexMemorySearch(db: Database.Database, opts?: ReindexOptions): Promise<ReindexSearchResult>;
|
|
@@ -410,6 +420,8 @@ interface SurfaceResult {
|
|
|
410
420
|
lexical_rank?: number;
|
|
411
421
|
semantic_rank?: number;
|
|
412
422
|
semantic_similarity?: number;
|
|
423
|
+
related_source_id?: string;
|
|
424
|
+
match_type?: "direct" | "related";
|
|
413
425
|
}
|
|
414
426
|
interface SurfaceResponse {
|
|
415
427
|
count: number;
|
|
@@ -831,4 +843,4 @@ declare function formatNarrativeBoot(layers: {
|
|
|
831
843
|
*/
|
|
832
844
|
declare function boot(db: Database.Database, opts?: WarmBootOptions): WarmBootResult;
|
|
833
845
|
|
|
834
|
-
export { type AgentMemoryHttpServer, type ReflectInput as AppReflectInput, type ReflectProgressEvent as AppReflectProgressEvent, type AutoIngestWatcher, type AutoIngestWatcherOptions, type BootResult, type ConflictInfo, type ConflictType, type CreateMemoryInput, type DedupScoreBreakdown, type EmbeddingProvider, type EmbeddingProviderConfig, type EmbeddingProviderKind, type EmbeddingProviderOptions, type EmbeddingStatus, type EvictionCandidate, type ExportResult, type FeedbackEventInput, type FeedbackEventRecord, type FeedbackSource, type FeedbackSummary, type GovernResult, type GuardAction, type GuardInput, type GuardResult, type HttpJobStatus, type HttpServerOptions, type HybridRecallResponse, type HybridRecallResult, type IngestExtractedItem, type IngestResult, type IngestRunOptions, type MaintenanceJob, type MaintenancePhase, type MaintenanceStatus, type Memory, type MemoryType, type MergeContext, type MergePlan, type Path, type PendingEmbeddingRecord, type Priority, type RecallInput, type ReflectCheckpoint, type ReflectOptions, type ReflectProgressEvent$1 as ReflectProgressEvent, type ReflectRunResult, type ReflectRunners, type ReflectStats, type ReflectStep, type ReindexEmbeddingsResult, type ReindexInput, type ReindexProgressEvent, type ReindexSearchResult, type RememberInput, type SearchResult, type StatusResult, type StoredEmbedding, type SurfaceInput, type SurfaceIntent, type SurfaceResponse, type SurfaceResult, type SyncInput, type SyncResult, type TidyResult, type UpdateMemoryInput, type VectorSearchResult, type WarmBootOptions, type WarmBootResult, boot, buildFtsQuery, buildMergePlan, calculateVitality, classifyIngestType, completeMaintenanceJob, computeEvictionScore, contentHash, cosineSimilarity, countMemories, createEmbeddingProvider, createHttpServer, createInitialCheckpoint, createLocalHttpEmbeddingProvider, createMaintenanceJob, createMemory, createOpenAICompatibleEmbeddingProvider, createPath, decodeVector, deleteMemory, deletePath, encodeVector, exportMemories, extractIngestItems, failMaintenanceJob, findResumableMaintenanceJob, formatNarrativeBoot, formatRelativeDate, fuseHybridResults, fusionScore, getConfiguredEmbeddingProviderId, getDecayedMemories, getEmbedding, getEmbeddingProvider, getEmbeddingProviderConfigFromEnv, getEmbeddingProviderFromEnv, getFeedbackScore, getFeedbackSummary, getMaintenanceJob, getMemory, getMemoryStatus, getPath, getPathByUri, getPathsByDomain, getPathsByMemory, getPathsByPrefix, guard, healthcheckEmbeddingProvider, ingestText, isStaleContent, listMemories, listPendingEmbeddings, loadWarmBootLayers, markAllEmbeddingsPending, markEmbeddingFailed, markMemoryEmbeddingPending, parseUri, priorityPrior, rankEvictionCandidates, rebuildBm25Index, recallMemories, recallMemory, recordAccess, recordFeedbackEvent, recordPassiveFeedback, reflectMemories, reindexEmbeddings, reindexMemories, reindexMemorySearch, rememberMemory, runAutoIngestWatcher, runDecay, runGovern, runReflectOrchestrator, runTidy, searchBM25, searchByVector, slugify, splitIngestBlocks, startHttpServer, surfaceMemories, syncBatch, syncOne, tokenize, updateMaintenanceCheckpoint, updateMemory, upsertReadyEmbedding };
|
|
846
|
+
export { type AgentMemoryHttpServer, type ReflectInput as AppReflectInput, type ReflectProgressEvent as AppReflectProgressEvent, type AutoIngestWatcher, type AutoIngestWatcherOptions, type BootResult, type ConflictInfo, type ConflictType, type CreateMemoryInput, type DedupScoreBreakdown, type EmbeddingProvider, type EmbeddingProviderConfig, type EmbeddingProviderKind, type EmbeddingProviderOptions, type EmbeddingStatus, type EvictionCandidate, type ExportResult, type FeedbackEventInput, type FeedbackEventRecord, type FeedbackSource, type FeedbackSummary, type GovernResult, type GuardAction, type GuardInput, type GuardResult, type HttpJobStatus, type HttpServerOptions, type HybridRecallResponse, type HybridRecallResult, type IngestExtractedItem, type IngestResult, type IngestRunOptions, type MaintenanceJob, type MaintenancePhase, type MaintenanceStatus, type Memory, type MemoryType, type MergeContext, type MergePlan, type Path, type PendingEmbeddingRecord, type Priority, type RecallInput, type ReflectCheckpoint, type ReflectOptions, type ReflectProgressEvent$1 as ReflectProgressEvent, type ReflectRunResult, type ReflectRunners, type ReflectStats, type ReflectStep, type ReindexEmbeddingsResult, type ReindexInput, type ReindexProgressEvent, type ReindexSearchResult, type RelatedLink, type RememberInput, type SearchResult, type StatusResult, type StoredEmbedding, type SurfaceInput, type SurfaceIntent, type SurfaceResponse, type SurfaceResult, type SyncInput, type SyncResult, type TidyResult, type UpdateMemoryInput, type VectorSearchResult, type WarmBootOptions, type WarmBootResult, boot, buildFtsQuery, buildMergePlan, calculateVitality, classifyIngestType, completeMaintenanceJob, computeEvictionScore, contentHash, cosineSimilarity, countMemories, createEmbeddingProvider, createHttpServer, createInitialCheckpoint, createLocalHttpEmbeddingProvider, createMaintenanceJob, createMemory, createOpenAICompatibleEmbeddingProvider, createPath, decodeVector, deleteMemory, deletePath, encodeVector, exportMemories, extractIngestItems, failMaintenanceJob, fetchRelatedLinks, findResumableMaintenanceJob, formatNarrativeBoot, formatRelativeDate, fuseHybridResults, fusionScore, getConfiguredEmbeddingProviderId, getDecayedMemories, getEmbedding, getEmbeddingProvider, getEmbeddingProviderConfigFromEnv, getEmbeddingProviderFromEnv, getFeedbackScore, getFeedbackSummary, getMaintenanceJob, getMemory, getMemoryStatus, getPath, getPathByUri, getPathsByDomain, getPathsByMemory, getPathsByPrefix, guard, healthcheckEmbeddingProvider, ingestText, isStaleContent, listMemories, listPendingEmbeddings, loadWarmBootLayers, markAllEmbeddingsPending, markEmbeddingFailed, markMemoryEmbeddingPending, parseUri, priorityPrior, rankEvictionCandidates, rebuildBm25Index, recallMemories, recallMemory, recordAccess, recordFeedbackEvent, recordPassiveFeedback, reflectMemories, reindexEmbeddings, reindexMemories, reindexMemorySearch, rememberMemory, runAutoIngestWatcher, runDecay, runGovern, runReflectOrchestrator, runTidy, searchBM25, searchByVector, slugify, splitIngestBlocks, startHttpServer, surfaceMemories, syncBatch, syncOne, tokenize, updateMaintenanceCheckpoint, updateMemory, upsertReadyEmbedding };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// AgentMemory
|
|
1
|
+
// AgentMemory — Sleep-cycle memory for AI agents
|
|
2
2
|
|
|
3
3
|
// src/core/memory.ts
|
|
4
4
|
import { createHash as createHash2 } from "crypto";
|
|
@@ -1433,21 +1433,20 @@ async function searchVectorBranch(db, query, opts) {
|
|
|
1433
1433
|
before: opts.before
|
|
1434
1434
|
});
|
|
1435
1435
|
}
|
|
1436
|
-
function
|
|
1437
|
-
const existingIds = new Set(results.map((r) => r.memory.id));
|
|
1436
|
+
function fetchRelatedLinks(db, sourceIds, agentId, excludeIds, maxPerSource = 5) {
|
|
1438
1437
|
const related = [];
|
|
1439
|
-
for (const
|
|
1438
|
+
for (const sourceId of sourceIds) {
|
|
1440
1439
|
const links = db.prepare(
|
|
1441
1440
|
`SELECT l.target_id, l.weight, m.*
|
|
1442
1441
|
FROM links l
|
|
1443
1442
|
JOIN memories m ON m.id = l.target_id
|
|
1444
1443
|
WHERE l.agent_id = ? AND l.source_id = ?
|
|
1445
1444
|
ORDER BY l.weight DESC
|
|
1446
|
-
LIMIT
|
|
1447
|
-
).all(agentId,
|
|
1445
|
+
LIMIT ?`
|
|
1446
|
+
).all(agentId, sourceId, maxPerSource);
|
|
1448
1447
|
for (const link of links) {
|
|
1449
|
-
if (
|
|
1450
|
-
|
|
1448
|
+
if (excludeIds.has(link.target_id)) continue;
|
|
1449
|
+
excludeIds.add(link.target_id);
|
|
1451
1450
|
const relatedMemory = {
|
|
1452
1451
|
id: link.id,
|
|
1453
1452
|
content: link.content,
|
|
@@ -1470,12 +1469,30 @@ function expandRelated(db, results, agentId, maxTotal) {
|
|
|
1470
1469
|
};
|
|
1471
1470
|
related.push({
|
|
1472
1471
|
memory: relatedMemory,
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
match_type: "related"
|
|
1472
|
+
sourceId,
|
|
1473
|
+
weight: link.weight
|
|
1476
1474
|
});
|
|
1477
1475
|
}
|
|
1478
1476
|
}
|
|
1477
|
+
return related;
|
|
1478
|
+
}
|
|
1479
|
+
function expandRelated(db, results, agentId, maxTotal) {
|
|
1480
|
+
const existingIds = new Set(results.map((r) => r.memory.id));
|
|
1481
|
+
const links = fetchRelatedLinks(
|
|
1482
|
+
db,
|
|
1483
|
+
results.map((r) => r.memory.id),
|
|
1484
|
+
agentId,
|
|
1485
|
+
existingIds
|
|
1486
|
+
);
|
|
1487
|
+
const related = links.map((link) => {
|
|
1488
|
+
const sourceResult = results.find((r) => r.memory.id === link.sourceId);
|
|
1489
|
+
return {
|
|
1490
|
+
memory: link.memory,
|
|
1491
|
+
score: (sourceResult?.score ?? 0) * link.weight * 0.6,
|
|
1492
|
+
related_source_id: link.sourceId,
|
|
1493
|
+
match_type: "related"
|
|
1494
|
+
};
|
|
1495
|
+
});
|
|
1479
1496
|
const directResults = results.map((r) => ({
|
|
1480
1497
|
...r,
|
|
1481
1498
|
match_type: "direct"
|
|
@@ -2501,7 +2518,8 @@ async function surfaceMemories(db, input) {
|
|
|
2501
2518
|
}),
|
|
2502
2519
|
lexical_rank: signal.queryRank ?? signal.recentRank ?? signal.taskRank,
|
|
2503
2520
|
semantic_rank: signal.semanticRank,
|
|
2504
|
-
semantic_similarity: signal.semanticSimilarity
|
|
2521
|
+
semantic_similarity: signal.semanticSimilarity,
|
|
2522
|
+
match_type: "direct"
|
|
2505
2523
|
};
|
|
2506
2524
|
}).sort((left, right) => {
|
|
2507
2525
|
if (right.score !== left.score) return right.score - left.score;
|
|
@@ -2510,6 +2528,42 @@ async function surfaceMemories(db, input) {
|
|
|
2510
2528
|
if (left.memory.priority !== right.memory.priority) return left.memory.priority - right.memory.priority;
|
|
2511
2529
|
return right.memory.updated_at.localeCompare(left.memory.updated_at);
|
|
2512
2530
|
}).slice(0, limit);
|
|
2531
|
+
if (input.related) {
|
|
2532
|
+
const existingIds = new Set(results.map((r) => r.memory.id));
|
|
2533
|
+
const links = fetchRelatedLinks(
|
|
2534
|
+
db,
|
|
2535
|
+
results.map((r) => r.memory.id),
|
|
2536
|
+
agentId,
|
|
2537
|
+
existingIds
|
|
2538
|
+
);
|
|
2539
|
+
const relatedResults = links.map((link) => {
|
|
2540
|
+
const sourceResult = results.find((r) => r.memory.id === link.sourceId);
|
|
2541
|
+
const feedbackSummary = getFeedbackSummary(db, link.memory.id, agentId);
|
|
2542
|
+
return {
|
|
2543
|
+
memory: link.memory,
|
|
2544
|
+
score: (sourceResult?.score ?? 0) * link.weight * 0.6,
|
|
2545
|
+
semantic_score: 0,
|
|
2546
|
+
lexical_score: 0,
|
|
2547
|
+
task_match: 0,
|
|
2548
|
+
vitality: link.memory.vitality,
|
|
2549
|
+
priority_prior: priorityPrior(link.memory.priority),
|
|
2550
|
+
feedback_score: feedbackSummary.score,
|
|
2551
|
+
feedback_summary: feedbackSummary,
|
|
2552
|
+
reason_codes: [`type:${link.memory.type}`, "related"],
|
|
2553
|
+
related_source_id: link.sourceId,
|
|
2554
|
+
match_type: "related"
|
|
2555
|
+
};
|
|
2556
|
+
});
|
|
2557
|
+
const maxTotal = Math.floor(limit * 1.5);
|
|
2558
|
+
const combined = [...results, ...relatedResults].sort((a, b) => b.score - a.score).slice(0, maxTotal);
|
|
2559
|
+
return {
|
|
2560
|
+
count: combined.length,
|
|
2561
|
+
query: trimmedQuery,
|
|
2562
|
+
task: trimmedTask,
|
|
2563
|
+
intent: input.intent,
|
|
2564
|
+
results: combined
|
|
2565
|
+
};
|
|
2566
|
+
}
|
|
2513
2567
|
return {
|
|
2514
2568
|
count: results.length,
|
|
2515
2569
|
query: trimmedQuery,
|
|
@@ -3129,6 +3183,8 @@ function formatRecallResponse(result) {
|
|
|
3129
3183
|
vector_rank: row.vector_rank,
|
|
3130
3184
|
bm25_score: row.bm25_score,
|
|
3131
3185
|
vector_score: row.vector_score,
|
|
3186
|
+
related_source_id: row.related_source_id,
|
|
3187
|
+
match_type: row.match_type,
|
|
3132
3188
|
updated_at: row.memory.updated_at
|
|
3133
3189
|
}))
|
|
3134
3190
|
};
|
|
@@ -3153,6 +3209,8 @@ function formatSurfaceResponse(result) {
|
|
|
3153
3209
|
feedback_score: row.feedback_score,
|
|
3154
3210
|
feedback_summary: row.feedback_summary,
|
|
3155
3211
|
reason_codes: row.reason_codes,
|
|
3212
|
+
related_source_id: row.related_source_id,
|
|
3213
|
+
match_type: row.match_type,
|
|
3156
3214
|
updated_at: row.memory.updated_at
|
|
3157
3215
|
}))
|
|
3158
3216
|
};
|
|
@@ -3322,7 +3380,11 @@ function createHttpServer(options) {
|
|
|
3322
3380
|
emotion_val: asNumber(body.emotion_val),
|
|
3323
3381
|
agent_id: asString(body.agent_id) ?? defaultAgentId,
|
|
3324
3382
|
conservative: asBoolean(body.conservative),
|
|
3325
|
-
provider: options?.provider
|
|
3383
|
+
provider: options?.provider,
|
|
3384
|
+
emotion_tag: asString(body.emotion_tag),
|
|
3385
|
+
source_session: asString(body.source_session),
|
|
3386
|
+
source_context: asString(body.source_context),
|
|
3387
|
+
observed_at: asString(body.observed_at)
|
|
3326
3388
|
});
|
|
3327
3389
|
sendJson(res, 200, result);
|
|
3328
3390
|
return;
|
|
@@ -3337,7 +3399,12 @@ function createHttpServer(options) {
|
|
|
3337
3399
|
query,
|
|
3338
3400
|
limit: asNumber(body.limit),
|
|
3339
3401
|
agent_id: asString(body.agent_id) ?? defaultAgentId,
|
|
3340
|
-
provider: options?.provider
|
|
3402
|
+
provider: options?.provider,
|
|
3403
|
+
related: asBoolean(body.related),
|
|
3404
|
+
after: asString(body.after),
|
|
3405
|
+
before: asString(body.before),
|
|
3406
|
+
recency_boost: asNumber(body.recency_boost),
|
|
3407
|
+
emotion_tag: asString(body.emotion_tag)
|
|
3341
3408
|
});
|
|
3342
3409
|
sendJson(res, 200, formatRecallResponse(result));
|
|
3343
3410
|
return;
|
|
@@ -3357,7 +3424,12 @@ function createHttpServer(options) {
|
|
|
3357
3424
|
types,
|
|
3358
3425
|
limit: asNumber(body.limit),
|
|
3359
3426
|
agent_id: asString(body.agent_id) ?? defaultAgentId,
|
|
3360
|
-
provider: options?.provider
|
|
3427
|
+
provider: options?.provider,
|
|
3428
|
+
related: asBoolean(body.related),
|
|
3429
|
+
after: asString(body.after),
|
|
3430
|
+
before: asString(body.before),
|
|
3431
|
+
recency_boost: asNumber(body.recency_boost),
|
|
3432
|
+
emotion_tag: asString(body.emotion_tag)
|
|
3361
3433
|
});
|
|
3362
3434
|
sendJson(res, 200, formatSurfaceResponse(result));
|
|
3363
3435
|
return;
|
|
@@ -3674,6 +3746,7 @@ function runAutoIngestWatcher(options) {
|
|
|
3674
3746
|
const memoryMdPath = join2(workspaceDir, "MEMORY.md");
|
|
3675
3747
|
const debounceMs = options.debounceMs ?? 1200;
|
|
3676
3748
|
const initialScan = options.initialScan ?? true;
|
|
3749
|
+
const ingestDaily = process.env.AGENT_MEMORY_AUTO_INGEST_DAILY === "1";
|
|
3677
3750
|
const logger = options.logger ?? console;
|
|
3678
3751
|
const timers = /* @__PURE__ */ new Map();
|
|
3679
3752
|
const watchers = [];
|
|
@@ -3694,6 +3767,10 @@ function runAutoIngestWatcher(options) {
|
|
|
3694
3767
|
const isTrackedMarkdownFile = (absPath) => {
|
|
3695
3768
|
if (!absPath.endsWith(".md")) return false;
|
|
3696
3769
|
if (resolve(absPath) === memoryMdPath) return true;
|
|
3770
|
+
if (!ingestDaily) {
|
|
3771
|
+
const basename = absPath.split("/").pop() ?? "";
|
|
3772
|
+
if (/^\d{4}-\d{2}-\d{2}\.md$/.test(basename)) return false;
|
|
3773
|
+
}
|
|
3697
3774
|
const rel = relative(memoryDir, absPath).replace(/\\/g, "/");
|
|
3698
3775
|
if (rel.startsWith("..") || rel === "") return false;
|
|
3699
3776
|
return !rel.includes("/");
|
|
@@ -3949,6 +4026,7 @@ export {
|
|
|
3949
4026
|
exportMemories,
|
|
3950
4027
|
extractIngestItems,
|
|
3951
4028
|
failMaintenanceJob,
|
|
4029
|
+
fetchRelatedLinks,
|
|
3952
4030
|
findResumableMaintenanceJob,
|
|
3953
4031
|
formatNarrativeBoot,
|
|
3954
4032
|
formatRelativeDate,
|