@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
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"better-sqlite3@11.10.0": true, "esbuild@0.27.4": true}
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,120 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 5.0.1 (2026-03-20)
|
|
4
|
+
|
|
5
|
+
### 🐛 Fixes
|
|
6
|
+
|
|
7
|
+
- **auto-ingest**: Daily log files (`YYYY-MM-DD.md`) are now skipped by default.
|
|
8
|
+
Only `MEMORY.md` (curated memory) is watched and ingested. Daily logs are raw
|
|
9
|
+
journals that often contain noise — they should be processed through the
|
|
10
|
+
memory-sync cron pipeline instead.
|
|
11
|
+
- New environment variable `AGENT_MEMORY_AUTO_INGEST_DAILY=1` restores the
|
|
12
|
+
previous behavior of ingesting all `.md` files in the `memory/` directory.
|
|
13
|
+
|
|
14
|
+
## 5.0.0 (2026-03-20)
|
|
15
|
+
|
|
16
|
+
### 🧠 Memory Intelligence
|
|
17
|
+
|
|
18
|
+
v5 is a major feature release that adds six intelligence capabilities to the
|
|
19
|
+
memory layer. All features are backward-compatible with v4 workflows.
|
|
20
|
+
|
|
21
|
+
Design document: `docs/design/0018-v5-memory-intelligence.md`
|
|
22
|
+
|
|
23
|
+
#### F1: Memory Links (记忆关联)
|
|
24
|
+
|
|
25
|
+
- Automatic link creation during `syncOne()`: after a successful `add` or
|
|
26
|
+
`merge`, candidates with `dedup_score ∈ [0.45, 0.82)` are saved as `related`
|
|
27
|
+
links (up to 5 per memory)
|
|
28
|
+
- `recall` and `surface` accept a new `related: boolean` parameter. When true,
|
|
29
|
+
top-K results are expanded with linked memories from the `links` table
|
|
30
|
+
(capped at `limit * 1.5`, with score scaled by `original_score * link_weight * 0.6`)
|
|
31
|
+
- Related memories are tagged with `match_type: 'related'` and
|
|
32
|
+
`related_source_id` in results so the agent knows why they appeared
|
|
33
|
+
- New MCP tool **`link`**: manually create or remove associations
|
|
34
|
+
(`relation`: `related` | `supersedes` | `contradicts`, with optional `weight`)
|
|
35
|
+
|
|
36
|
+
#### F2: Conflict Detection (冲突检测)
|
|
37
|
+
|
|
38
|
+
- Write Guard (`guard.ts`) now iterates over multiple candidates instead of
|
|
39
|
+
only the top-1 match
|
|
40
|
+
- Three conflict signal types detected between incoming content and existing
|
|
41
|
+
candidates:
|
|
42
|
+
- **Negation**: one side contains negation words the other does not
|
|
43
|
+
- **Value**: same entity with different numeric values (IPs, ports, versions)
|
|
44
|
+
- **Status**: one side marked done/cancelled while the other is in-progress
|
|
45
|
+
- Conflict score (0–1) is computed from weighted signals. Conflicts above 0.5
|
|
46
|
+
are reported in `GuardResult.conflicts` and propagated to `SyncResult`
|
|
47
|
+
- **Conflict Override rule**: when `dedup_score ≥ 0.93` and a `status` or
|
|
48
|
+
`value` conflict is detected, the guard action is forced from `skip` to
|
|
49
|
+
`update` — preventing legitimate state changes (e.g. TODO → DONE) from being
|
|
50
|
+
silently deduplicated. `negation` conflicts do not trigger override (higher
|
|
51
|
+
false-positive rate)
|
|
52
|
+
- Writes are never blocked by conflict detection — the agent decides what to do
|
|
53
|
+
|
|
54
|
+
#### F3: Temporal Recall (时间维度召回)
|
|
55
|
+
|
|
56
|
+
- `recall` and `surface` accept new optional parameters:
|
|
57
|
+
- `after` / `before` (ISO 8601) — time-range filter at the SQL layer for
|
|
58
|
+
both BM25 and vector search paths
|
|
59
|
+
- `recency_boost` (0–1) — blends a recency decay signal into the fusion
|
|
60
|
+
score: `final = (1 - boost) * base + boost * e^(-days/30)`
|
|
61
|
+
- BM25 and vector search functions (`searchBM25`, `searchByVector`) extended
|
|
62
|
+
with `after` / `before` filter support
|
|
63
|
+
|
|
64
|
+
#### F4: Passive Feedback (被动反馈)
|
|
65
|
+
|
|
66
|
+
- `FeedbackSource` type extended to `"recall" | "surface" | "passive"`
|
|
67
|
+
- When `recall` records access, the top-3 results automatically receive a
|
|
68
|
+
positive passive feedback event (value 0.7, vs 1.0 for explicit feedback)
|
|
69
|
+
- Rate-limited: max 3 passive feedback events per memory per 24-hour window
|
|
70
|
+
- Anti-N+1: deduplication check uses a single batch `WHERE memory_id IN (...)`
|
|
71
|
+
query instead of per-memory `SELECT COUNT(*)`
|
|
72
|
+
|
|
73
|
+
#### F5: Semantic Decay (语义衰减)
|
|
74
|
+
|
|
75
|
+
- New `isStaleContent(content, type)` function in `tidy.ts` detects
|
|
76
|
+
temporally-stale content via keyword pattern matching
|
|
77
|
+
- Pattern sets are scoped by memory type:
|
|
78
|
+
- `event`: broad matching (e.g. `正在`, `in progress`, `TODO`, `just now`)
|
|
79
|
+
- `knowledge`: anchored-start-only patterns (e.g. `^TODO:`, `^WIP:`) to
|
|
80
|
+
avoid false positives on knowledge descriptions containing those words
|
|
81
|
+
- `identity` and `emotion`: exempt from semantic decay
|
|
82
|
+
- Age thresholds: `in_progress` > 7d, `pending` > 14d, `ephemeral` > 3d
|
|
83
|
+
- Matched memories have their `vitality` multiplied by the pattern's
|
|
84
|
+
`decay_factor`
|
|
85
|
+
- `TidyResult` now includes `staleDecayed` count
|
|
86
|
+
|
|
87
|
+
#### F6: Memory Provenance (记忆溯源)
|
|
88
|
+
|
|
89
|
+
- Schema migration v6 → v7: three new nullable columns on `memories`:
|
|
90
|
+
- `source_session` — originating session ID
|
|
91
|
+
- `source_context` — trigger context (≤200 chars)
|
|
92
|
+
- `observed_at` — when the event actually happened (distinct from write time)
|
|
93
|
+
- `Memory` interface and `CreateMemoryInput` updated with provenance fields
|
|
94
|
+
- MCP `remember` tool accepts `session_id`, `context`, `observed_at`
|
|
95
|
+
- `recall` / `surface` results include provenance fields when present
|
|
96
|
+
- `guard.ts` `timeProximity()` now prefers `observed_at` over regex-guessed
|
|
97
|
+
timestamps from content/URI/source
|
|
98
|
+
|
|
99
|
+
### 🧰 Tooling
|
|
100
|
+
|
|
101
|
+
- MCP toolset expanded from **10 → 11 tools** (added `link`)
|
|
102
|
+
- MCP server version string updated to `5.0.0`
|
|
103
|
+
|
|
104
|
+
### ✅ Tests
|
|
105
|
+
|
|
106
|
+
- Added `tests/v5/intelligence.test.ts` with **25 new test cases** covering
|
|
107
|
+
all six v5 features
|
|
108
|
+
- Total test count: **96** (up from 69 in v4.2)
|
|
109
|
+
|
|
110
|
+
### 📦 Schema
|
|
111
|
+
|
|
112
|
+
- Database schema version: **7** (from 6)
|
|
113
|
+
- Migration is additive (nullable columns only) — safe to upgrade in place
|
|
114
|
+
- Rollback: ignore new columns, delete new link/feedback rows by type
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
3
118
|
## 4.2.0 (2026-03-19)
|
|
4
119
|
|
|
5
120
|
### 🛡️ Anti-Noise Hardening
|
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
<a href="https://www.npmjs.com/package/@smyslenny/agent-memory"><img src="https://img.shields.io/npm/v/@smyslenny/agent-memory" alt="npm" /></a>
|
|
11
11
|
<a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="License: MIT" /></a>
|
|
12
12
|
<a href="https://nodejs.org/"><img src="https://img.shields.io/badge/Node.js-%E2%89%A518-green.svg" alt="Node.js" /></a>
|
|
13
|
-
<a href="https://modelcontextprotocol.io/"><img src="https://img.shields.io/badge/MCP-
|
|
13
|
+
<a href="https://modelcontextprotocol.io/"><img src="https://img.shields.io/badge/MCP-11_tools-orange.svg" alt="MCP" /></a>
|
|
14
14
|
</p>
|
|
15
15
|
|
|
16
16
|
**English** | [简体中文说明](docs/README-zh.md)
|
|
@@ -22,7 +22,7 @@ AgentMemory is a SQLite-first memory layer for AI agents. It lets an agent:
|
|
|
22
22
|
- **maintain** them over time with `reflect`, `reindex`, and feedback signals
|
|
23
23
|
- **integrate** through **CLI**, **MCP stdio**, or **HTTP/SSE**
|
|
24
24
|
|
|
25
|
-
Current release: **`
|
|
25
|
+
Current release: **`5.0.1`**.
|
|
26
26
|
|
|
27
27
|
Without an embedding provider, AgentMemory still works in **BM25-only mode**.
|
|
28
28
|
With one configured, it adds **hybrid recall** and **semantic dedup**.
|
|
@@ -40,16 +40,36 @@ That means it is designed around the things agent runtimes actually need:
|
|
|
40
40
|
- a lifecycle path for decay, governance, reindexing, and recovery-friendly jobs
|
|
41
41
|
- a local-first deployment model that stays useful even without extra infra
|
|
42
42
|
|
|
43
|
-
Core building blocks
|
|
43
|
+
Core building blocks:
|
|
44
44
|
|
|
45
45
|
- **Typed memories**: `identity`, `emotion`, `knowledge`, `event`
|
|
46
46
|
- **URI paths** for stable addressing
|
|
47
|
-
- **Write Guard** with semantic dedup + typed merge policy
|
|
47
|
+
- **Write Guard** with semantic dedup + typed merge policy + conflict detection
|
|
48
48
|
- **Hybrid retrieval**: BM25 first, optional vector search
|
|
49
|
+
- **Memory links** with automatic association and related-memory expansion
|
|
50
|
+
- **Temporal recall** with time filtering and recency boost
|
|
49
51
|
- **Context-aware surfacing** for task/recent-turn driven context injection
|
|
52
|
+
- **Passive feedback** that records usage signals automatically
|
|
53
|
+
- **Semantic decay** that detects stale content beyond pure time-based Ebbinghaus
|
|
54
|
+
- **Memory provenance** for tracking where and when each memory originated
|
|
50
55
|
- **Lifecycle jobs**: `reflect`, `reindex`, job checkpoints, feedback signals
|
|
51
56
|
- **Three transport modes**: CLI, MCP stdio, HTTP/SSE
|
|
52
57
|
|
|
58
|
+
### New in v5: Memory Intelligence
|
|
59
|
+
|
|
60
|
+
v5 adds six features that turn agent-memory from a durable store into an
|
|
61
|
+
intelligent memory layer. All features are backward-compatible — existing
|
|
62
|
+
v4 workflows continue to work unchanged.
|
|
63
|
+
|
|
64
|
+
| Feature | What it does |
|
|
65
|
+
| --- | --- |
|
|
66
|
+
| **F1 Memory Links** | Automatically detects semantically related memories during write and builds lightweight associations. `recall` and `surface` support `related` expansion to pull in linked memories. A new `link` tool allows manual link management. |
|
|
67
|
+
| **F2 Conflict Detection** | Write Guard now scans candidates for contradictions (negation, value changes, status changes). Conflicts are reported in the sync result without blocking writes. A **Conflict Override** rule ensures status updates (e.g. TODO → DONE) are not incorrectly deduplicated. |
|
|
68
|
+
| **F3 Temporal Recall** | `recall` and `surface` accept `after`, `before`, and `recency_boost` parameters. Time filtering happens at the SQL layer for both BM25 and vector paths. Recency boost blends a time-decay signal into the fusion score. |
|
|
69
|
+
| **F4 Passive Feedback** | When `recall` returns results and records access, positive feedback is automatically logged for the top-3 hits. Rate-limited to 3 passive events per memory per 24 hours. |
|
|
70
|
+
| **F5 Semantic Decay** | The `tidy` phase now detects stale content through keyword pattern matching (e.g. "in progress", "TODO:", "just now"). Patterns are scoped by memory type — `event` uses broad matching, `knowledge` uses anchored-start-only patterns. `identity` and `emotion` are exempt. |
|
|
71
|
+
| **F6 Memory Provenance** | Memories can carry `source_session`, `source_context`, and `observed_at` metadata. This tracks where and when a memory originated, separate from its write timestamp. Schema migrated from v6 → v7. |
|
|
72
|
+
|
|
53
73
|
## 2) How is it different from a vector DB, a RAG pipeline, or memory summaries?
|
|
54
74
|
|
|
55
75
|
| Thing | Good at | What AgentMemory adds |
|
|
@@ -177,18 +197,19 @@ npx agent-memory reflect all
|
|
|
177
197
|
}
|
|
178
198
|
```
|
|
179
199
|
|
|
180
|
-
Available MCP tools
|
|
200
|
+
Available MCP tools:
|
|
181
201
|
|
|
182
|
-
- `remember`
|
|
183
|
-
- `recall`
|
|
184
|
-
- `recall_path`
|
|
185
|
-
- `boot`
|
|
186
|
-
- `forget`
|
|
187
|
-
- `reflect`
|
|
188
|
-
- `status`
|
|
189
|
-
- `ingest`
|
|
190
|
-
- `reindex`
|
|
191
|
-
- `surface`
|
|
202
|
+
- `remember` — store a memory (supports provenance: `session_id`, `context`, `observed_at`)
|
|
203
|
+
- `recall` — hybrid search (supports `related`, `after`, `before`, `recency_boost`)
|
|
204
|
+
- `recall_path` — read or list memories by URI
|
|
205
|
+
- `boot` — load startup memories (narrative or JSON)
|
|
206
|
+
- `forget` — soft-decay or hard-delete a memory
|
|
207
|
+
- `reflect` — run sleep cycle phases (decay, tidy, govern)
|
|
208
|
+
- `status` — memory system statistics
|
|
209
|
+
- `ingest` — extract structured memories from markdown
|
|
210
|
+
- `reindex` — rebuild BM25 index and optional embeddings
|
|
211
|
+
- `surface` — context-aware readonly surfacing (supports `related`, `after`, `before`, `recency_boost`)
|
|
212
|
+
- `link` — manually create or remove associations between memories
|
|
192
213
|
|
|
193
214
|
### C. HTTP API
|
|
194
215
|
|
|
@@ -274,6 +295,22 @@ export AGENT_MEMORY_EMBEDDING_API_KEY=your-api-key
|
|
|
274
295
|
Or use `AGENT_MEMORY_EMBEDDING_PROVIDER=local-http` for a local HTTP embedding
|
|
275
296
|
service. If no provider is configured, AgentMemory falls back to BM25-only.
|
|
276
297
|
|
|
298
|
+
## Environment variables
|
|
299
|
+
|
|
300
|
+
| Variable | Default | Description |
|
|
301
|
+
| --- | --- | --- |
|
|
302
|
+
| `AGENT_MEMORY_DB` | `./agent-memory.db` | SQLite database path |
|
|
303
|
+
| `AGENT_MEMORY_AGENT_ID` | `default` | Agent scope for multi-agent setups |
|
|
304
|
+
| `AGENT_MEMORY_MAX_MEMORIES` | `200` | Maximum memories retained during `reflect govern` |
|
|
305
|
+
| `AGENT_MEMORY_AUTO_INGEST` | `1` | Set to `0` to disable the auto-ingest file watcher |
|
|
306
|
+
| `AGENT_MEMORY_AUTO_INGEST_DAILY` | _(unset)_ | Set to `1` to include daily log files (`YYYY-MM-DD.md`) in auto-ingest. By default, only `MEMORY.md` is watched. |
|
|
307
|
+
| `AGENT_MEMORY_WORKSPACE` | `~/.openclaw/workspace` | Workspace directory for the auto-ingest watcher |
|
|
308
|
+
| `AGENT_MEMORY_EMBEDDING_PROVIDER` | _(unset)_ | `openai-compatible` or `local-http` |
|
|
309
|
+
| `AGENT_MEMORY_EMBEDDING_BASE_URL` | _(unset)_ | Base URL for the embedding endpoint |
|
|
310
|
+
| `AGENT_MEMORY_EMBEDDING_MODEL` | _(unset)_ | Embedding model name |
|
|
311
|
+
| `AGENT_MEMORY_EMBEDDING_DIMENSION` | _(unset)_ | Embedding vector dimension |
|
|
312
|
+
| `AGENT_MEMORY_EMBEDDING_API_KEY` | _(unset)_ | API key for the embedding provider |
|
|
313
|
+
|
|
277
314
|
## Documentation map
|
|
278
315
|
|
|
279
316
|
- [Architecture](docs/architecture.md)
|
package/dist/bin/agent-memory.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// AgentMemory
|
|
2
|
+
// AgentMemory — Sleep-cycle memory for AI agents
|
|
3
3
|
var __defProp = Object.defineProperty;
|
|
4
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
5
|
var __esm = (fn, res) => function __init() {
|
|
@@ -1649,21 +1649,20 @@ async function searchVectorBranch(db, query, opts) {
|
|
|
1649
1649
|
before: opts.before
|
|
1650
1650
|
});
|
|
1651
1651
|
}
|
|
1652
|
-
function
|
|
1653
|
-
const existingIds = new Set(results.map((r) => r.memory.id));
|
|
1652
|
+
function fetchRelatedLinks(db, sourceIds, agentId, excludeIds, maxPerSource = 5) {
|
|
1654
1653
|
const related = [];
|
|
1655
|
-
for (const
|
|
1654
|
+
for (const sourceId of sourceIds) {
|
|
1656
1655
|
const links = db.prepare(
|
|
1657
1656
|
`SELECT l.target_id, l.weight, m.*
|
|
1658
1657
|
FROM links l
|
|
1659
1658
|
JOIN memories m ON m.id = l.target_id
|
|
1660
1659
|
WHERE l.agent_id = ? AND l.source_id = ?
|
|
1661
1660
|
ORDER BY l.weight DESC
|
|
1662
|
-
LIMIT
|
|
1663
|
-
).all(agentId,
|
|
1661
|
+
LIMIT ?`
|
|
1662
|
+
).all(agentId, sourceId, maxPerSource);
|
|
1664
1663
|
for (const link of links) {
|
|
1665
|
-
if (
|
|
1666
|
-
|
|
1664
|
+
if (excludeIds.has(link.target_id)) continue;
|
|
1665
|
+
excludeIds.add(link.target_id);
|
|
1667
1666
|
const relatedMemory = {
|
|
1668
1667
|
id: link.id,
|
|
1669
1668
|
content: link.content,
|
|
@@ -1686,12 +1685,30 @@ function expandRelated(db, results, agentId, maxTotal) {
|
|
|
1686
1685
|
};
|
|
1687
1686
|
related.push({
|
|
1688
1687
|
memory: relatedMemory,
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
match_type: "related"
|
|
1688
|
+
sourceId,
|
|
1689
|
+
weight: link.weight
|
|
1692
1690
|
});
|
|
1693
1691
|
}
|
|
1694
1692
|
}
|
|
1693
|
+
return related;
|
|
1694
|
+
}
|
|
1695
|
+
function expandRelated(db, results, agentId, maxTotal) {
|
|
1696
|
+
const existingIds = new Set(results.map((r) => r.memory.id));
|
|
1697
|
+
const links = fetchRelatedLinks(
|
|
1698
|
+
db,
|
|
1699
|
+
results.map((r) => r.memory.id),
|
|
1700
|
+
agentId,
|
|
1701
|
+
existingIds
|
|
1702
|
+
);
|
|
1703
|
+
const related = links.map((link) => {
|
|
1704
|
+
const sourceResult = results.find((r) => r.memory.id === link.sourceId);
|
|
1705
|
+
return {
|
|
1706
|
+
memory: link.memory,
|
|
1707
|
+
score: (sourceResult?.score ?? 0) * link.weight * 0.6,
|
|
1708
|
+
related_source_id: link.sourceId,
|
|
1709
|
+
match_type: "related"
|
|
1710
|
+
};
|
|
1711
|
+
});
|
|
1695
1712
|
const directResults = results.map((r) => ({
|
|
1696
1713
|
...r,
|
|
1697
1714
|
match_type: "direct"
|
|
@@ -2192,7 +2209,8 @@ async function surfaceMemories(db, input) {
|
|
|
2192
2209
|
}),
|
|
2193
2210
|
lexical_rank: signal.queryRank ?? signal.recentRank ?? signal.taskRank,
|
|
2194
2211
|
semantic_rank: signal.semanticRank,
|
|
2195
|
-
semantic_similarity: signal.semanticSimilarity
|
|
2212
|
+
semantic_similarity: signal.semanticSimilarity,
|
|
2213
|
+
match_type: "direct"
|
|
2196
2214
|
};
|
|
2197
2215
|
}).sort((left, right) => {
|
|
2198
2216
|
if (right.score !== left.score) return right.score - left.score;
|
|
@@ -2201,6 +2219,42 @@ async function surfaceMemories(db, input) {
|
|
|
2201
2219
|
if (left.memory.priority !== right.memory.priority) return left.memory.priority - right.memory.priority;
|
|
2202
2220
|
return right.memory.updated_at.localeCompare(left.memory.updated_at);
|
|
2203
2221
|
}).slice(0, limit);
|
|
2222
|
+
if (input.related) {
|
|
2223
|
+
const existingIds = new Set(results.map((r) => r.memory.id));
|
|
2224
|
+
const links = fetchRelatedLinks(
|
|
2225
|
+
db,
|
|
2226
|
+
results.map((r) => r.memory.id),
|
|
2227
|
+
agentId,
|
|
2228
|
+
existingIds
|
|
2229
|
+
);
|
|
2230
|
+
const relatedResults = links.map((link) => {
|
|
2231
|
+
const sourceResult = results.find((r) => r.memory.id === link.sourceId);
|
|
2232
|
+
const feedbackSummary = getFeedbackSummary(db, link.memory.id, agentId);
|
|
2233
|
+
return {
|
|
2234
|
+
memory: link.memory,
|
|
2235
|
+
score: (sourceResult?.score ?? 0) * link.weight * 0.6,
|
|
2236
|
+
semantic_score: 0,
|
|
2237
|
+
lexical_score: 0,
|
|
2238
|
+
task_match: 0,
|
|
2239
|
+
vitality: link.memory.vitality,
|
|
2240
|
+
priority_prior: priorityPrior(link.memory.priority),
|
|
2241
|
+
feedback_score: feedbackSummary.score,
|
|
2242
|
+
feedback_summary: feedbackSummary,
|
|
2243
|
+
reason_codes: [`type:${link.memory.type}`, "related"],
|
|
2244
|
+
related_source_id: link.sourceId,
|
|
2245
|
+
match_type: "related"
|
|
2246
|
+
};
|
|
2247
|
+
});
|
|
2248
|
+
const maxTotal = Math.floor(limit * 1.5);
|
|
2249
|
+
const combined = [...results, ...relatedResults].sort((a, b) => b.score - a.score).slice(0, maxTotal);
|
|
2250
|
+
return {
|
|
2251
|
+
count: combined.length,
|
|
2252
|
+
query: trimmedQuery,
|
|
2253
|
+
task: trimmedTask,
|
|
2254
|
+
intent: input.intent,
|
|
2255
|
+
results: combined
|
|
2256
|
+
};
|
|
2257
|
+
}
|
|
2204
2258
|
return {
|
|
2205
2259
|
count: results.length,
|
|
2206
2260
|
query: trimmedQuery,
|
|
@@ -3357,6 +3411,8 @@ function formatRecallResponse(result) {
|
|
|
3357
3411
|
vector_rank: row.vector_rank,
|
|
3358
3412
|
bm25_score: row.bm25_score,
|
|
3359
3413
|
vector_score: row.vector_score,
|
|
3414
|
+
related_source_id: row.related_source_id,
|
|
3415
|
+
match_type: row.match_type,
|
|
3360
3416
|
updated_at: row.memory.updated_at
|
|
3361
3417
|
}))
|
|
3362
3418
|
};
|
|
@@ -3381,6 +3437,8 @@ function formatSurfaceResponse(result) {
|
|
|
3381
3437
|
feedback_score: row.feedback_score,
|
|
3382
3438
|
feedback_summary: row.feedback_summary,
|
|
3383
3439
|
reason_codes: row.reason_codes,
|
|
3440
|
+
related_source_id: row.related_source_id,
|
|
3441
|
+
match_type: row.match_type,
|
|
3384
3442
|
updated_at: row.memory.updated_at
|
|
3385
3443
|
}))
|
|
3386
3444
|
};
|
|
@@ -3550,7 +3608,11 @@ function createHttpServer(options) {
|
|
|
3550
3608
|
emotion_val: asNumber(body.emotion_val),
|
|
3551
3609
|
agent_id: asString(body.agent_id) ?? defaultAgentId,
|
|
3552
3610
|
conservative: asBoolean(body.conservative),
|
|
3553
|
-
provider: options?.provider
|
|
3611
|
+
provider: options?.provider,
|
|
3612
|
+
emotion_tag: asString(body.emotion_tag),
|
|
3613
|
+
source_session: asString(body.source_session),
|
|
3614
|
+
source_context: asString(body.source_context),
|
|
3615
|
+
observed_at: asString(body.observed_at)
|
|
3554
3616
|
});
|
|
3555
3617
|
sendJson(res, 200, result);
|
|
3556
3618
|
return;
|
|
@@ -3565,7 +3627,12 @@ function createHttpServer(options) {
|
|
|
3565
3627
|
query,
|
|
3566
3628
|
limit: asNumber(body.limit),
|
|
3567
3629
|
agent_id: asString(body.agent_id) ?? defaultAgentId,
|
|
3568
|
-
provider: options?.provider
|
|
3630
|
+
provider: options?.provider,
|
|
3631
|
+
related: asBoolean(body.related),
|
|
3632
|
+
after: asString(body.after),
|
|
3633
|
+
before: asString(body.before),
|
|
3634
|
+
recency_boost: asNumber(body.recency_boost),
|
|
3635
|
+
emotion_tag: asString(body.emotion_tag)
|
|
3569
3636
|
});
|
|
3570
3637
|
sendJson(res, 200, formatRecallResponse(result));
|
|
3571
3638
|
return;
|
|
@@ -3585,7 +3652,12 @@ function createHttpServer(options) {
|
|
|
3585
3652
|
types,
|
|
3586
3653
|
limit: asNumber(body.limit),
|
|
3587
3654
|
agent_id: asString(body.agent_id) ?? defaultAgentId,
|
|
3588
|
-
provider: options?.provider
|
|
3655
|
+
provider: options?.provider,
|
|
3656
|
+
related: asBoolean(body.related),
|
|
3657
|
+
after: asString(body.after),
|
|
3658
|
+
before: asString(body.before),
|
|
3659
|
+
recency_boost: asNumber(body.recency_boost),
|
|
3660
|
+
emotion_tag: asString(body.emotion_tag)
|
|
3589
3661
|
});
|
|
3590
3662
|
sendJson(res, 200, formatSurfaceResponse(result));
|
|
3591
3663
|
return;
|
|
@@ -3719,7 +3791,7 @@ function getAgentId() {
|
|
|
3719
3791
|
}
|
|
3720
3792
|
function printHelp() {
|
|
3721
3793
|
console.log(`
|
|
3722
|
-
\u{1F9E0} AgentMemory
|
|
3794
|
+
\u{1F9E0} AgentMemory \u2014 Sleep-cycle memory for AI agents
|
|
3723
3795
|
|
|
3724
3796
|
Usage: agent-memory <command> [options]
|
|
3725
3797
|
|