mirror of
https://github.com/rohitg00/agentmemory.git
synced 2026-09-14 20:16:33 +08:00
v0.8.11
38 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
0023af2c53 |
fix: iii-sdk v0.11 getContext crash — add logger shim, v0.8.11 (#146)
* fix: replace getContext() with logger shim for iii-sdk v0.11 compatibility
iii-sdk v0.11 dropped getContext() entirely. 32 src/functions/*.ts files still
imported and called it, crashing node dist/index.mjs on first import with:
SyntaxError: module 'iii-sdk' does not provide an export named 'getContext'
- Add src/logger.ts: thin stderr shim (info/warn/error) with identical call signature
- Remove getContext import and const ctx = getContext() from all 32 function files
- Replace ctx.logger.* with logger.* throughout
- Fix search.ts registerFunction({ id: ... }) -> registerFunction('id') for v0.11 API
- Update 45 test mock blocks from vi.mock("iii-sdk") to vi.mock("../src/logger.js")
- Bump to v0.8.11
Tests: 731/731 pass. Binary starts cleanly. Closes #116.
* fix: bump version to 0.8.11 in plugin.json, export-import supported versions, and test
|
||
|
|
5d70ecfb3c |
feat: migrate agentmemory to iii v0.11 and add upgrade command (#116)
* feat: migrate agentmemory to iii v0.11 and add upgrade command
Migrate the codebase from legacy iii-sdk v0.3 APIs to v0.11 trigger/register patterns, update runtime configs, and align stream/state behavior with newer engine semantics. Add a new `agentmemory upgrade` CLI command so users can refresh dependencies and iii runtime components with one entrypoint.
* chore: remove pnpm lockfile from migration PR
Drop pnpm-lock.yaml from this branch to keep the migration PR focused on source and config changes only.
* fix(ci): sync npm lockfile with iii-sdk v0.11 dependency
Update package-lock.json so npm ci in CI matches package.json after the iii-sdk migration.
* fix(ci): resolve build parse errors after v0.11 migration
Fix malformed braces introduced during API migration in triggers/health/branch-aware files so tsdown build passes in CI.
* fix: harden migration follow-up fixes and audits
Apply the reviewed v0.11 follow-up fixes across runtime, docs, and tests by tightening validation, correcting upgrade/error handling, and adding missing audit coverage on state mutations. This also addresses stream fallback behavior, lock consistency, retention source-bucket cleanup, and test/mock alignment so build and test remain green.
* fix: address 9 unresolved CodeRabbit findings on iii v0.11 migration
CodeRabbit flagged 9 remaining issues on #116 — all real. Each was
verified against the current branch code before applying. Two
findings were deliberately skipped as policy/scope issues and are
documented at the bottom.
### Applied (9 real findings)
- src/triggers/api.ts — api.ts numeric query param validation:
multiple sites forwarded `parseInt(params.limit)` result to the
downstream function without a Number.isFinite check. A non-numeric
query value produced NaN at the iii-sdk trigger boundary. Added
parseOptionalInt and parseOptionalFloat helpers at the top of the
file, wired into api::crystal-list, api::lesson-list, and
api::insight-list (5 sites total).
- src/triggers/api.ts — api::observe, api::context, api::session::start,
api::session::end were forwarding req.body verbatim to sdk.trigger
with no validation. Added explicit type checks mirroring the existing
api::search pattern, construct a sanitized payload object before
triggering.
- src/cli.ts — p.confirm() can return a cancel Symbol on Ctrl+C, which
is truthy, so the upgrade path ran even when the user cancelled.
Added p.isCancel() check and explicit boolean comparison.
- src/cli.ts — removed dead `failed` flag in runUpgrade: every caller
already calls process.exit(1) immediately, so the final `if (failed)`
branch was unreachable. Simplified requireSuccess accordingly.
- src/functions/leases.ts — mem::lease-renew recorded audit events as
"lease_acquire", which conflated renewals with first claims. Renamed
the audit event to "lease_renew" so downstream audit filters can tell
the two operations apart.
- src/functions/relations.ts — the pair lock
`mem:${firstId}:${secondId}` serialized concurrent relate(A,B) calls
with identical pairs, but did NOT protect concurrent relate(A,B) +
relate(A,C). Both modify memory A's `relatedIds` array, which is a
classic last-writer-wins race producing lost relation edges. Fixed
by replacing the pair lock with nested per-entity locks in canonical
sort order: withKeyedLock(mem:firstId) wrapping withKeyedLock(mem:secondId).
Since the ids are sorted deterministically, no deadlock is possible.
- src/functions/sketches.ts + src/functions/summarize.ts + new
src/functions/audit.ts safeAudit helper — recordAudit was awaited
after kv.set calls. An audit write failure would reject and the
caller would see an error even though the target state was already
persisted. New safeAudit wrapper swallows audit errors and logs them
via ctx.logger.warn, preserving the mutation's success. Applied to
all 11 audit sites in sketches.ts and the single site in summarize.ts.
- src/mcp/server.ts — three issues in the MCP handler:
1. memory_profile's refresh flag used `args.refresh === "true"`,
ignoring boolean `true` from MCP clients that send proper types.
Now accepts both.
2. memory_sketch_create built sketchPayload with
`asNonEmptyString(args.title)` which could return undefined,
then forwarded that to the downstream function. Added explicit
validation + 400 response at the MCP boundary.
3. memory_recall, memory_team_feed, memory_audit_query used
`(args.limit as number) || 10` which replaced an explicit 0 with
10. Changed to typeof check so explicit 0 (rare but legal) is
preserved.
- src/functions/governance.ts — mem::governance-bulk used Promise.all
for the delete batch, which fails fast on the first error. The audit
record still said `deleted: candidates.length` even if only half
actually succeeded. Switched to Promise.allSettled, split results
into successfulIds and failures arrays, record audit with both counts
plus the per-failure details for traceability.
- src/functions/mesh.ts — mem::mesh-register, mem::mesh-sync,
mem::mesh-receive, mem::mesh-remove all dereferenced `data.*` without
checking that data was passed. A TypeError would bubble up on null
payload. Added early null/type guards returning structured errors.
- src/functions/obsidian-export.ts — resolveVaultDir(data.vaultDir)
was called without validating that vaultDir was a string, and
`new Set(data.types)` without validating types was an array of
strings. Added explicit validation returning 400-style error
responses.
- src/functions/retention.ts — the eviction loop silently swallowed
kv.delete errors via a bare `continue`. Added ctx.logger.warn on
catch, included memoryId and sourceBucket in the log, and now
returns `failed` count alongside `evicted` in the response.
- src/viewer/index.html — two WebSocket bugs:
1. connectWs assigned to the mutable global state.ws before binding
handlers, so old sockets could have their callbacks fire and
mutate retry/direct state after state.ws was overwritten by a
new socket. Fixed by creating a local `ws` variable, binding
all handlers to it, only then assigning state.ws = ws. Each
handler guards `if (state.ws !== ws) return` so stale callbacks
are dropped.
2. handleStreamEvent routed EVERY incoming event to routeWsMessage,
so non-observation events (session.activity, etc.) were being
treated as timeline observations and causing UI confusion. Added
a looksLikeObservation helper + event_type gate that only routes
real observation payloads.
- test/retention.test.ts — added an explicit sourceBucket eviction
test that seeds a semantic memory at high age, runs retention-score,
then runs retention-evict at high threshold and asserts BOTH
KV.semantic and KV.memories are empty. Proves the candidate.sourceBucket
branch added in this PR actually routes to the right bucket.
- src/types.ts — side fix: the ExportData.version union on line 254
used comma separators instead of pipes in 3 positions (0.7.9,
0.8.0, 0.8.1 → needed | between them). tsdown strips types so the
build passed, but tsc --noEmit would have thrown and any IDE showed
squiggles. Pre-existing latent bug, fixed while in the file.
### Deliberately skipped
- retention.ts eviction audit (CodeRabbit asked to add recordAudit
to the eviction loop): policy change, not a bug fix. Verified:
auto-forget.ts, evict.ts, retention-evict, remember-forget all
skip audit by convention — only governance audits. Adding audit
everywhere is a policy decision tracked in issue #125.
- file-index.ts sequential → parallel session lookup: micro-opt,
the loop is already cache-backed, negligible savings, not worth
the readability cost.
Tests: 655/655. Build clean.
* fix(api): harden request validation at HTTP boundaries
Validate and sanitize session, observe, and context inputs plus numeric query params before forwarding to memory functions, returning 400 for invalid values instead of propagating malformed payloads. Also remove duplicate CLI command registration introduced during merge resolution.
* fix: address 6 new CodeRabbit findings on iii v0.11 migration (#116 round 2)
CodeRabbit's second review pass on #116 flagged 6 real issues introduced
by the previous round of fixes (commit
|
||
|
|
3bad5430ed |
fix: SessionStart context gate (#143) + retention-evict semantic leak (#124) (#145)
* fix: stop burning Claude Pro tokens on every tool call (#143) 0.8.8 fixed the agentmemory-side Claude API burn (where the engine called Claude via the user's ANTHROPIC_API_KEY for per-observation compression). That addressed #138 for users with API keys, but it missed the second and much larger token-burn path: the PreToolUse hook writing context to stdout. Claude Code reads PreToolUse stdout and prepends it to the model's next turn. src/hooks/pre-tool-use.ts was POSTing /agentmemory/enrich on every Edit/Write/Read/Glob/Grep tool call and piping up to 4000 chars of response context into stdout. At ~20 tool calls per user message this silently injected ~20K tokens per message into Claude Code's input window — all charged against the user's Claude Pro allocation because Claude Code was the one sending them to Anthropic. 4 messages drained the cap, which matches @adrianricardo's report. session-start.ts had the same pattern (injected once per session, smaller blast radius). Fix: gate both hooks on AGENTMEMORY_INJECT_CONTEXT, default false. - pre-tool-use.ts: when disabled, exit immediately — no stdin read, no fetch, no stdout write. The hot path (~20x per message) becomes a no-op Node startup. - session-start.ts: when disabled, still POST /agentmemory/session/start so the session gets registered for observation tracking, but never write context to stdout. The session registration is cheap and doesn't touch Claude Code's input window. - src/config.ts: new isContextInjectionEnabled() helper. - src/index.ts: startup banner prints 'Context injection: OFF (default, #143)' on normal startup and a loud WARNING when opt-in is enabled. - test/context-injection.test.ts: 5 subprocess tests that spawn the compiled pre-tool-use.mjs and session-start.mjs hooks, feed real JSON payloads via stdin, and assert stdout is empty in all the off/default paths. Also asserts the disabled path exits under 1s and the opt-in path with an unreachable backend still exits cleanly. - README .env section: new AGENTMEMORY_INJECT_CONTEXT entry. - CHANGELOG [0.8.10] with prominent 'Behavior change' banner. Observations are still captured via PostToolUse regardless of the flag — the memory store and MCP search tools are completely unaffected by this change. The fix only severs the path where agentmemory silently shoves memory context into the user's Claude Code conversation. Bumps to 0.8.10 (main + @agentmemory/mcp shim). Test count: 724 passing (was 719 + 5 new). * chore: rewrite #143 CHANGELOG entry with corrected diagnosis PreToolUse stdout is NOT injected into the model context — per the Claude Code hook docs, only UserPromptSubmit and SessionStart stdout are injected. My initial #143 PR description and CHANGELOG claimed PreToolUse was the smoking gun behind 'Pro allocation burned in 4 messages', which is wrong. What's actually true: - SessionStart stdout injection IS real (~1-2K tokens per session) - PreToolUse stdout goes to debug log only — no tokens - Claude Pro's Claude Code quotas are tight by design (Anthropic has publicly acknowledged this); 4 messages to burn is plausible with or without agentmemory installed The gate on pre-tool-use.ts is still worth keeping as a resource cleanup (skips a 20x-per-message Node+HTTP hot path) and as forward-compat protection in case Claude Code ever changes PreToolUse hook contract. But the CHANGELOG entry has to stop claiming it saves tokens when it doesn't. * fix: mem::retention-evict no longer leaks semantic memories (#124) The eviction loop was unconditionally calling kv.delete(KV.memories, id) for every below-threshold candidate, but retention scores are computed for both episodic (KV.memories) and semantic (KV.semantic) memories. When a candidate came from KV.semantic, the delete silently became a no-op (key wasn't in mem:memories to begin with) and the semantic row stayed alive forever with a sub-threshold score. Semantic memories could not be evicted by this path at all. Fix: - Add a source: "episodic" | "semantic" discriminator to RetentionScore - Tag it at score creation in both loops of mem::retention-score - Branch the delete in mem::retention-evict on candidate.source, routing to KV.memories or KV.semantic accordingly - Pre-0.8.10 retention rows with no source field are treated as episodic for backwards-compat so upgraded stores continue to evict their old rows without re-scoring first - Response now includes evictedEpisodic and evictedSemantic counts so callers can see what was removed from each scope Adds 3 regression tests to test/retention.test.ts: - Scoring tags rows with the correct source - Evicting a mixed set of below-threshold episodic + semantic candidates removes both from their respective scopes - Legacy-shape score rows with no source field still evict to mem:memories (backwards-compat) Full suite: 727 passing (was 724 + 3 new). * review: probe namespaces for legacy retention rows (#124, round 2) CodeRabbit caught a real backwards-compat hole in the #124 fix: pre-0.8.10 stores already contain semantic retention rows with no source field (because the old mem::retention-score scored KV.semantic before the discriminator existed). My first fix defaulted missing source to episodic, which meant those legacy semantic rows still got delete-routed to KV.memories — the exact no-op that stranded them in the first place. Fix: when candidate.source is undefined, probe KV.memories first for the memoryId; if it's there, route to episodic, otherwise route to semantic. Count the resolved source in the response. Adds one new test case: a pre-0.8.10 semantic memory with a legacy-shape retention row (no source field) gets evicted from mem:semantic, not silently no-op'd. Existing 'defaults to episodic' test is kept and retargeted to the genuinely-episodic legacy case. Also fixes a README nit: the AGENTMEMORY_INJECT_CONTEXT comment previously implied SessionStart fires on every tool turn. It's once per session. Now broken out into two bullets explaining what each hook does differently, with the note that only SessionStart actually reaches the model (PreToolUse stdout is debug-log only per Claude Code docs). Full suite: 728 passing (was 727 + 1 new). * review: audit retention evictions + assert persisted source (#124 round 3) CodeRabbit round 3 findings, both real: 1. retention-evict performs structural deletes (memories / semantic / retention scores / access logs) but was not calling recordAudit(). Repo learnings say state-changing functions must be auditable except for read-path bookkeeping. Now emits one batched audit row per non-zero eviction sweep: operation: 'delete' functionId: 'mem::retention-evict' targetIds: every evicted memoryId details: { threshold, evicted, evictedEpisodic, evictedSemantic, reason: 'retention score below threshold' } Zero-eviction sweeps intentionally do NOT write an audit row (no state change, no need to flood the audit log during health checks). 2. The #124 scoring test only checked result.scores (transient response) but not the persisted mem:retention rows. Eviction reads back from stored rows, so a regression in kv.set/serialization would have still passed the old assertion. Now also does kv.get('mem:retention', id) and asserts { source: ... }. Two new tests: - Retention evict with a mixed set of 2 episodic + 1 semantic candidates writes exactly one audit row with all 3 ids in targetIds and the correct evictedEpisodic/Semantic breakdown in details. - Retention evict with zero candidates writes zero audit rows. Full suite: 730 passing (was 728 + 2 new). * review: audit retention-score + parallelize writes (#124 round 4) CodeRabbit round 3 outside-diff findings, both addressed: 1. mem::retention-score was persisting schema-relevant writes to KV.retentionScores (1000+ rows in a mature store) but never called recordAudit(). Per the repo audit-coverage policy, state-changing functions need an audit row. Added a single batched audit event per rescore: operation: 'retention_score' (new audit op — added to the AuditEntry union in types.ts) functionId: 'mem::retention-score' targetIds: [] (intentionally empty — a mature store can have 1000+ ids per sweep; flooding the audit log with every memoryId on every cron tick is worse than recording just the summary counts) details: { total, episodic, semantic, tiers, config } Zero-memory stores intentionally skip the audit call. 2. The per-memory kv.set inside the score loop was O(n) sequential round-trips. Refactored to collect pendingWrites: [id, entry][] while iterating, then flush with Promise.all at the end. On a mature store with 1000+ memories this is ~10x faster (depends on backend pipelining). Test updates: - Added 'mem::retention-score emits audit row per rescore' covering the new audit call, targetIds=[], and details.episodic/semantic. - Existing '#124 audit evict' and 'zero-evict skip audit' tests now filter the audit log by functionId === 'mem::retention-evict' because retention-score also writes one row per sweep now. Full suite: 731 passing (was 730 + 1 new, existing tests retargeted). |
||
|
|
f72c7a54fc |
fix: plugin auto-wires MCP + sandbox-safe skills (#139) (#141)
* fix: Claude Code plugin auto-wires MCP + sandbox-safe skills (#139) Two fixes reported in #139: 1. The Claude Code plugin (rohitg00/agentmemory) only shipped hooks and skills; it did not auto-register any MCP server. Users had to configure the @agentmemory/mcp stdio server separately, which the README didn't make clear. Add plugin/.mcp.json so /plugin install agentmemory@agentmemory wires up the MCP server automatically when the plugin is enabled. 2. The `recall` and `session-history` skills used inline bash pre-execution blocks (`!$(curl -s ... ${VAR:-default})`) with shell expansion, which Claude Code's sandbox rejects by pattern match with "Contains expansion" — no way to bypass except for Claude to reconstruct the curl call manually, as the reporter had to work around. Rewrite all four plugin skills (recall / remember / forget / session-history) as pure prompts that tell Claude to use the MCP tools directly: memory_smart_search, memory_save, memory_sessions, memory_governance_delete. No bash, no sandbox issues, no shell escaping. Skills also run faster — no curl subprocess fork on every invocation. Also tighten the README Claude Code install snippet to note that the plugin now registers hooks + skills AND auto-wires the MCP server in one step. Bumps to 0.8.9. 707 tests still pass (no behavioral changes to server code; only plugin assets). * review: implement the MCP tools the new skills call (#139) CodeRabbit flagged that the rewritten plugin skills reference memory_smart_search and memory_governance_delete, but the standalone MCP shim (@agentmemory/mcp) only exposed 5 tools: memory_save, memory_recall, memory_sessions, memory_export, memory_audit. At runtime the skills would have thrown "Unknown tool" the first time they ran. Add the missing handlers to src/mcp/standalone.ts: - memory_smart_search — aliases memory_recall, falling back to substring search over the in-memory KV store. The standalone shim has no engine behind it, so BM25/vector/graph aren't available, but the substring match is good enough for plugin usage on small personal memory stores. - memory_governance_delete — deletes memories by id. Accepts memoryIds as an array or a comma-separated string, returns {deleted, requested, reason}. Throws on missing/empty input, silently skips unknown ids. Also normalize memory_save concepts/files: they now accept both arrays (what the new skills send) and CSV strings (what the old skills and legacy clients send). New normalizeList() helper centralizes the logic. Fix memory_sessions to honour a limit arg (default 20) — it was previously returning every session in the store. Update the forget skill wording per CodeRabbit's nit: make it explicit that memory_governance_delete only takes memoryIds, and that deleting a whole session means collecting all memory IDs from that session via search first. Adds 8 regression tests to test/mcp-standalone.test.ts covering: - memory_save with array concepts/files - memory_save with CSV concepts/files (legacy path) - memory_smart_search substring fallback - memory_sessions limit - memory_governance_delete array path - memory_governance_delete CSV path - memory_governance_delete missing/empty validation - memory_governance_delete unknown-id skip Full suite: 715 passing (was 707 + 8 new). * review: reject empty search query + fix skill troubleshooting paths (#139) CodeRabbit round 2: 1. src/mcp/standalone.ts memory_smart_search accepted '' as a query and used .includes('') which matches every memory. In the forget flow this would surface unrelated memory IDs for deletion. Now throws 'query is required' on missing/empty/ whitespace-only input. Also broadens the search corpus from just title+content to include files, concepts, sessionIds, and id — so users can /forget by file path, concept name, or session ID, as the skill docs already promise. 2. All four skill files (recall, remember, forget, session-history) said 'check the agentmemory engine is running on localhost:3111' when tools are missing. Wrong troubleshooting path: the stdio MCP shim spawned by Claude Code via .mcp.json has no REST API, no port, no localhost. The correct checks are /plugin list, /mcp, and restarting Claude Code after install. Updated all four skills. Adds 2 new regression tests to test/mcp-standalone.test.ts: - memory_smart_search rejects empty/whitespace/missing query - memory_smart_search finds memories by file, concept, or id Full suite: 717 passing. * review: tighten content/limit validation in standalone MCP (#139) CodeRabbit round 3: 1. memory_save cast args.content as string and called .trim(), which throws a runtime TypeError if content is a number, object, null, etc. Replace the cast with a proper typeof guard that returns the clean 'content is required' error for any non-string input. 2. memory_smart_search trimmed rawQuery for emptiness but then lowercased the *untrimmed* value, so a query like ' bcrypt ' would fail substring matches with trailing whitespace. Trim first, then lowercase. 3. (args.limit as number) || 10 is fragile — it treats 0 and NaN the same, silently accepts negative/Infinity values, and has no upper bound so a malicious or buggy caller could request a million memories in one slice(). Add parseLimit() helper that: - rejects non-number/non-string types (booleans, objects, arrays) - rejects NaN, Infinity, and non-positive values - clamps to MAX_LIMIT=100 via Math.min - Math.floor()s to force integer - falls back to a per-call default (10 for search, 20 for sessions, 50 for audit) Applied to all three limit sites: memory_smart_search, memory_sessions, memory_audit. Adds 2 regression tests: - memory_save rejects 42 / {} / [] / null / undefined / true without crashing on .trim() - parseLimit falls back on bogus values and clamps 99999 -> 100 Full suite: 719 passing (was 717 + 2 new). |
||
|
|
281e10ca8c |
fix: stop burning Claude tokens on every PostToolUse hook (#138) (#140)
* fix: stop burning Claude tokens on every PostToolUse hook (#138) mem::observe was firing mem::compress unconditionally on every PostToolUse hook, which called Claude via the user's ANTHROPIC_API_KEY to compress each raw observation into a structured summary. On an active coding session (50-200 tool calls/hour) this silently burned hundreds of thousands of Claude API tokens within minutes. Reported by @olcor1 on a fresh Docker install — his token allocation was gone in 20 minutes. Make per-observation LLM compression opt-in. - New env var AGENTMEMORY_AUTO_COMPRESS, default `false`. When false, observe.ts builds a zero-LLM synthetic CompressedObservation from raw tool I/O (title from toolName, narrative from truncated input/output, files extracted from file_path/pattern/etc., type inferred from camelCase-normalized tool name) and stores + indexes it. Recall and BM25 search still work. - New src/functions/compress-synthetic.ts with buildSyntheticCompression(). - src/functions/observe.ts gates the compress trigger on the flag and writes the synthetic observation + stream events when disabled. - Startup banner now logs "Auto-compress: OFF (default, #138)" or a loud warning when opt-in is on, so the mode is never silent. - Regression test: test/auto-compress.test.ts covers the default path (no mem::compress fired), explicit opt-in, tool-name-to-type mapping, file-path extraction, narrative truncation, and the post_tool_failure→error mapping. Bumps to 0.8.8 (main package + shim). 707 tests pass. **Migration**: users who were relying on LLM-generated summaries set AGENTMEMORY_AUTO_COMPRESS=true in ~/.agentmemory/.env and restart. Existing compressed observations on disk are untouched. * review: address CodeRabbit findings on #140 - compress-synthetic.ts:92 — use the fallback toolName for inferType so both title and type derive from the same resolved value - test/auto-compress.test.ts — vi.resetModules() in beforeEach to prevent cached observe.js from seeing stale env var state between the default, opt-in, and explicit-off test cases |
||
|
|
b864a7d268 |
fix: ship iii-config.docker.yaml in the npm tarball (#136) (#137)
docker-compose.yml mounts `./iii-config.docker.yaml:/app/config.yaml:ro` but the `files` array in package.json only shipped `iii-config.yaml`. Docker resolves missing bind sources by silently creating them as empty directories, so `npx @agentmemory/agentmemory` mounted an empty dir at /app/config.yaml and iii-engine crashed with: Error: Failed to read config file '/app/config.yaml': Is a directory (os error 21) Fix: add iii-config.docker.yaml to package.json `files`. Also adds a regression test in test/consistency.test.ts that parses every `./<path>:<container>` bind mount in docker-compose.yml and asserts the source file is shipped via the `files` array, so this class of bug can't reach a release again. Bumps main package + shim to 0.8.7 and adds CHANGELOG [0.8.7]. |
||
|
|
416fa15af4 |
chore: release 0.8.6 — scope the MCP shim as @agentmemory/mcp (#134)
0.8.5's publish workflow got blocked on the unscoped `agentmemory-mcp` name by npm's name-similarity policy (there's an unrelated third-party package called `agent-memory-mcp`). Publishing the shim under the `@agentmemory` scope we already own sidesteps the conflict. Changes: - Rename packages/agentmemory-mcp → packages/mcp - Package name: agentmemory-mcp → @agentmemory/mcp (0.8.4 → 0.8.6) - Keep bin name `agentmemory-mcp` so `npm i -g @agentmemory/mcp` still installs a binary at `agentmemory-mcp` for muscle memory - Log prefix [agentmemory-mcp] → [@agentmemory/mcp] in standalone.ts and in-memory-kv.ts - README / integrations/openclaw / integrations/hermes / src/cli.ts all point at `npx -y @agentmemory/mcp` - .github/workflows/publish.yml working-directory and npm view queries target packages/mcp and @agentmemory/mcp - Shim dependency on @agentmemory/agentmemory bumped to ~0.8.6 - Main package 0.8.5 → 0.8.6 across the 8 version files - CHANGELOG [0.8.6] entry documenting the scope move |
||
|
|
3935aecdae | chore: bump version to 0.8.5 + add CHANGELOG (#133) | ||
|
|
95e089a37c |
chore: release 0.8.4
Two community contributions on top of 0.8.3 land as a patch release so they reach users immediately and so `npx agentmemory-mcp` ships to the npm registry for the first time (closing out #120 on the live release). - #122 (Jason Landbridge): memory_save persists to disk immediately after every call, not just on SIGINT/SIGTERM, so memories survive SIGKILL from agent sessions ending forcefully - #121 (Jason Landbridge): OpenCode MCP config format corrected — opencode.json with mcp/type:local/command array instead of the wrong .opencode/config.json with mcpServers Version bumped across package.json, src/version.ts, types.ts, export-import supportedVersions, plugin.json, shim package.json and its dependency on the main package (~0.8.4). package-lock.json regenerated. 684 tests passing, clean build. |
||
|
|
8a36fe7867 |
fix: retention scoring (#119) + npx agentmemory-mcp 404 (#120), release 0.8.3 (#123)
* fix: retention scoring (#119) + npx agentmemory-mcp 404 (#120), release 0.8.3 Issue #119 — retention score ignored agent-side reads `mem::retention-score` previously hardcoded `accessCount=0` and `accessTimestamps=[]` for episodic memories and used only a single-sample `lastAccessedAt` for semantic memories, so the time-frequency decay formula was a dead path. All read endpoints now record access events to a new `mem:access` KV namespace via a keyed-mutex'd access tracker: - mem::search, mem::smart-search (compact + expand), mem::context, mem::timeline, mem::file-context, mem::get-related, mem::working-context - retention.ts pre-fetches the full access log in one kv.list call, normalizes every row defensively, and builds an O(1) lookup Map - recordAccessBatch uses Promise.allSettled so a slow keyed-lock on one id does not block the rest of the batch - Bounded ring buffer of the last 20 access timestamps per memory - Backwards-compat fallback: pre-0.8.3 semantic memories with only the legacy sem.lastAccessedAt still score correctly - Corrupt lastAccessedAt values are NaN-safe via Date.parse + isFinite - reinforcementBoost is reported as the raw formula output, not the clamped residual Memory deletion sites (retention-evict, evict, auto-forget, governance-delete, governance-bulk, forget, import replace) now call deleteAccessLog to prevent mem:access from accumulating zombie entries. mem::export / mem::import and mem::snapshot-create / mem::snapshot-restore round-trip the new namespace so backup/restore cycles no longer zero out reinforcement signals. Issue #120 — npx agentmemory-mcp returned npm registry 404 The README instructed users to run `npx agentmemory-mcp`, but `agentmemory-mcp` only existed as a `bin` entry inside `@agentmemory/agentmemory`, not a real registry package. Two-part fix: - New sibling package `packages/agentmemory-mcp/` — a thin shim that depends on `@agentmemory/agentmemory` (~0.8.3, tilde to block 0.9.x supply-chain drift) and forwards to dist/standalone.mjs via the new `exports` field on the main package - Canonical `npx @agentmemory/agentmemory mcp` subcommand on the CLI for users who already have the main package installed - Removed the dead `agentmemory-mcp` bin from the main package so the shim owns the name unambiguously - publish.yml publishes both packages in order with idempotent guards and npm-view registry polling (no more fixed sleep) - All MCP install snippets in README + integrations/openclaw + hermes + shim README use `npx -y agentmemory-mcp` to skip install prompts Release 0.8.3 - 670 tests passing (665 + 11 new: access tracker, retention, smart-search integration, corrupt-input, kv.list failure path, Promise.allSettled resilience) - Version bumped across package.json, src/version.ts, types.ts, export-import supportedVersions, plugin.json - package-lock.json regenerated * fix: address CodeRabbit review feedback on #123 Real issues caught and fixed: - access-tracker: deleteAccessLog now takes the same mem:access:<id> keyed mutex used by recordAccess, eliminating the race where a concurrent delete could drop an in-flight RMW update and leave a stale access log for an evicted memory - access-tracker: normalizeAccessLog now coerces count to a non-negative integer, drops non-finite recent[] entries, truncates recent[] to the last 20 on read (enforcing the ring-buffer invariant), and guarantees count >= recent.length so a malformed row can't produce NaN downstream. count is NOT capped at 20 — it is the lifetime access counter, while recent[] is the 20-entry window - export-import: import path now rejects accessLogs arrays above MAX_ACCESS_LOGS (50_000), normalizes each entry via normalizeAccessLog, and drops entries whose memoryId is not in the imported memories set, so a crafted export can't blow up memory or resurrect zombie access rows for memories that don't exist - publish.yml: added a post-publish npm view polling loop for agentmemory-mcp mirroring the one that already guards the main package, so the workflow only succeeds when `npx agentmemory-mcp` is actually visible on the registry - CHANGELOG.md: added the missing [0.8.3] reference-style link target at the bottom to match the [0.8.2]/[0.8.1]/[0.8.0] pattern - README.md: standalone MCP inline examples now use `npx -y` to match the MCP config snippets and skip the install confirmation prompt Tests: 680/680 (+10 new — deleteAccessLog behavior, normalizeAccessLog invariants, malformed mem:access row handling in retention scoring). Findings deliberately not applied: - auto-forget.ts / remember.ts / evict.ts recordAudit calls: existing pattern in the codebase only audits governance deletes (user-initiated admin actions), not automatic eviction. Adding audit everywhere is a policy change, out of scope for this PR - evict.ts gating deleteAccessLog on memory delete success: current order is defensible, deleteAccessLog is already best-effort with its own try/catch, and calling it after a failed memory delete is harmless - snapshot.ts fail-fast on kv.list failure: inconsistent with the existing .catch(() => []) pattern used for observations in the same function - retention.ts semantic evict only deletes KV.memories rows: real bug but pre-existing on main (RetentionScore has no source/type field). Tracked separately — out of scope for this PR - bin.mjs fallback command: already present in the existing catch handler - Promise.all parallelization of delete+deleteAccessLog: micro optimization not worth the readability cost |
||
|
|
fa2aa980fb |
chore: bump version to 0.8.2 + add CHANGELOG (#117)
## Version bumped across - package.json + package-lock.json - plugin/.claude-plugin/plugin.json - src/version.ts (union type) - src/types.ts ExportData.version union - src/functions/export-import.ts supportedVersions set - test/export-import.test.ts assertion Also fixed the ExportData version union syntax: prior releases used commas (`| "0.7.9", "0.8.0", "0.8.1"`) instead of pipes, which would not work as intended. Fixed to a proper pipe-separated union. ## CHANGELOG.md New file documenting v0.8.2 in Keep-a-Changelog format. Sections: **Security (6 fixes)** — addresses CVEs in default deployments: - [CRITICAL] Stored XSS in viewer - [CRITICAL] curl|sh in CLI startup - [HIGH] Default 0.0.0.0 binding - [HIGH] Unauthenticated mesh sync - [MEDIUM] Path traversal in Obsidian export - [MEDIUM] Incomplete secret redaction **Added**: - agentmemory demo CLI command - benchmark/COMPARISON.md - integrations/openclaw/ gateway plugin - Token savings dashboard in CLI + viewer - Paste-this-prompt blocks - 60 custom SVG tags (30 dark + 30 light variants) - Real agent logos in Supported Agents grid **Changed**: - README redesigned with SVG tags, brand palette - Supported Agents grid reordered - Default ports bound to 127.0.0.1 - Hero stat row uses custom SVG cards **Fixed**: - Viewer cost calculation 100x underreporting - ObservationType union missing "image" - Dynamic imports inside eviction loops - OpenClaw /context payload contract - Cursor cell missing label - Codex logo 404 **Infrastructure**: - 654 tests (up from 646), 8 new security tests - All 60 SVGs validated - README consistency check updated |
||
|
|
7af05ecf78 | chore: bump version to 0.8.1 | ||
|
|
798700f2a3 | chore: bump version to 0.8.0 | ||
|
|
29cbaa7624 | chore: bump version to 0.7.9 | ||
|
|
e6366e5c03 |
fix: skills path ./skills/ instead of ../skills/ (#94)
Claude Code resolves skill paths relative to the plugin root (the directory containing .claude-plugin/), not relative to plugin.json. |
||
|
|
805620aca1 | chore: bump version to 0.7.8 | ||
|
|
740c7b90a1 |
fix: plugin hooks and skills validation errors (#100)
- hooks.json: wrap each hook in { hooks: [{ type, command }] } format
(Claude Code expects nested hooks array, not flat type/command)
- plugin.json: change skills from explicit file paths to directory
reference ["../skills/"] matching working plugin convention
|
||
|
|
8704131745 | chore: bump version to 0.7.7 | ||
|
|
fbded55b29 |
fix: plugin.json validation errors (#94)
- author: change from string to object {name, url}
- hooks: remove field (auto-loaded by convention from hooks/hooks.json)
- skills: change from directory string to explicit file path array
|
||
|
|
b81682da8b | chore: bump version to 0.7.6 | ||
|
|
69bb787629 |
feat: cross-encoder reranking, working memory, skill extraction (#93)
* feat: cross-encoder reranking, working memory, skill extraction (#90, #58, #57) - reranker.ts: opt-in cross-encoder rerank after hybrid search via RERANK_ENABLED=true, uses @xenova/transformers MiniLM-L-6-v2, graceful fallback when unavailable - working-memory.ts: core memory (pinned facts always in context) + auto-paging of archival memories by importance/recency/access score, 5 new functions (core-add, core-remove, core-list, working-context, auto-page) - skill-extract.ts: auto-generate reusable procedural skills from completed sessions via LLM, with reinforcement on re-extraction, skill-match for querying relevant skills (3 new functions) - ProceduralMemory type extended with expectedOutcome, tags, concepts, sourceObservationIds - 19 new tests, 646 total passing Closes #90, closes #58, closes #57 * fix: add 0.8.0 to supported import versions, bump plugin.json * fix: address CodeRabbit review — audit, fingerprint, guards, archive - skill-extract: reject non-completed sessions, fingerprint full procedure (title+trigger+steps) not just title, audit reinforcement - working-memory: add recordAudit for core-add/core-remove/auto-page, auto-page now archives to KV.memories instead of deleting - reranker: cache pipelineUnavailable to avoid repeated import retries - hybrid-search: rerank over larger pool (max(limit,20)) then slice - types: add skill_extract/core_add/core_remove/auto_page to AuditEntry * fix: address remaining CodeRabbit review findings - Parse RERANK_ENABLED with === "true" instead of truthy coercion - Remove unused project param from mem::skill-list - Remove unused sessionId/project/query params from mem::working-context - Use generateId("mem") for archived core entries to avoid ID collision * fix: address CodeRabbit round-2 findings - Make skill reinforcement idempotent (skip if sessionId already present) - Parallelize summary + observations fetch in skill-extract - Use continue instead of break for oversized unpinned core entries - Buffer access-counter writes with Promise.allSettled (non-blocking) - Decouple rerank window (fixed 20) from retrieval depth |
||
|
|
ea2eddce83 | chore: bump version to 0.7.5 | ||
|
|
1fa0dcefab | chore: bump version to 0.7.4 | ||
|
|
9c27eff610 |
feat: implement reflect — auto-synthesize insights from memory clusters (#89)
Adds mem::reflect: traverses knowledge graph, groups related memories by concept clusters, synthesizes higher-order insights via LLM. New files: - src/prompts/reflect.ts — LLM prompt for insight synthesis - src/functions/reflect.ts — 4 functions: reflect, insight-list, insight-search, insight-decay-sweep - test/reflect.test.ts — 13 tests New type: Insight (confidence-scored, fingerprint-deduped, decayable) New KV scope: mem:insights New MCP tools: memory_reflect, memory_insight_list (in ESSENTIAL set) New REST: POST /reflect, GET /insights, POST /insights/search Hooks into consolidation pipeline as "reflect" tier after semantic Review fixes applied: - Fixed project filter no-op (was discarding filter result) - Fixed BFS depth tracking (standard level-count pattern) - Added attribute-order constraint to LLM prompt - Whitelisted fields in api::insight-search (no raw body passthrough) - Fixed Jaccard fallback to compare document-id sets not concept strings 43 MCP tools, 103 REST endpoints, 627 tests passing |
||
|
|
034869b42c | chore: bump version to 0.7.3 | ||
|
|
031eff7322 | chore: bump version to 0.7.2 across all files | ||
|
|
e8f410b537 |
feat: v0.7.0 — lessons, tool visibility, auto-consolidation, obsidian export, npx bootstrap (#82)
* feat: v0.7.0 — lessons, tool visibility, auto-consolidation, obsidian export, npx bootstrap Five DX improvements based on competitive research against Mem0, Engram, CodeMem: 1. `npx agentmemory` zero-config startup - New CLI bootstrap (src/cli.ts) auto-detects and starts iii-engine - Tries `iii` binary first, falls back to `docker compose up -d` - Bundles iii-config.yaml and docker-compose.yml in dist/ 2. Simplified MCP tool surface (7 core tools by default) - AGENTMEMORY_TOOLS=all unlocks all 49 tools - Default: save, recall, consolidate, forget, sessions, diagnose, lesson_save - Call handler remains unfiltered — any tool callable by name 3. Auto-consolidation on session end - CONSOLIDATION_ENABLED defaults to true (was false) - Session-end hook: session/end → crystallize → consolidate → bridge sync - Consolidation pipeline always registered (timer gated by config) 4. First-class lesson memory type with confidence decay - Lesson interface: confidence (0-1), reinforcements, decayRate, source - 5 functions: lesson-save, lesson-recall, lesson-list, lesson-strengthen, lesson-decay-sweep - Dedup via SHA-256 fingerprint — duplicate saves strengthen existing - Crystal lessons auto-flow into lesson system at confidence 0.6 - Daily decay sweep with parallel KV writes 5. Obsidian-compatible Markdown export - Export to ~/.agentmemory/vault/ with YAML frontmatter + wikilinks - MOC.md (Map of Content) index file - Parallel KV reads, auto-export via OBSIDIAN_AUTO_EXPORT=true Stats: 49 MCP tools, 99 REST endpoints, 573 tests passing * docs: add AGENTS.md, fix tool/endpoint counts across README, plugin, cli - Create AGENTS.md with strict consistency rules for MCP tools, REST endpoints, versions, KV scopes, and audit operations - Fix MCP tool count: 38 → 41 across README.md (4 occurrences) - Fix REST endpoint count: 93/95 → 99 across README.md and index.ts - Fix plugin.json: version 0.6.1 → 0.7.0, tool count 5 → 41 - Fix cli.ts help text: 48+ → 41 MCP tools - Fix README api.ts path reference → triggers/api.ts * fix: address code review findings — consolidation guard, decay bug, async fs, export-import lessons Inline fixes: - Revert CONSOLIDATION_ENABLED to opt-in (=== "true"), matching original behavior - Add early-exit guard in consolidation-pipeline handler when disabled - Gate session-end crystallize+consolidation calls on CONSOLIDATION_ENABLED - Fix lesson decay over-decay bug: add lastDecayedAt to Lesson, compute incremental delta instead of reapplying full age every sweep run - Add LESSON_DECAY_ENABLED flag (default true) to gate the sweep timer Outside diff fixes: - Add lessons to export-import (export + import + replace cleanup) - Log warning instead of swallowing obsidian auto-export errors Nitpick fixes: - Switch obsidian-export to async fs/promises (mkdir, writeFile) - Add per-item try/catch in obsidian-export, return errors array - Replace governance_delete with smart_search in ESSENTIAL_TOOLS (non-destructive default) - Fix CLI whichBinary for Windows (uses "where" on win32) - Use dynamic port in CLI error message instead of hardcoded 3111 - Return 201 for newly created lessons, 200 for strengthened - Wrap lesson audit calls in try/catch so audit failure doesn't surface - Fix build script to not swallow tsdown failure - Remove exact tool count from test, use >=41 + uniqueness + required names - Add test/consistency.test.ts: validates version, tool count, README consistency - Add isConsolidationEnabled mock to consolidation-pipeline test 579 tests passing (573 original + 6 new consistency checks) * fix: guard remaining audit calls, correct endpoint count, add CI + npm publish Review fixes: - Wrap lesson_recall and lesson_strengthen audit calls in try/catch - Fix REST endpoint count: 99 → 100 (verified via grep) across index.ts, README.md, and AGENTS.md - Use regex in consistency test for README assertions (flexible phrasing) - Add consolidation gate tests: disabled returns early, force=true bypasses CI/CD: - Add .github/workflows/ci.yml — test on Node 18/20/22 - Add .github/workflows/publish.yml — auto-publish to npm on GitHub release (uses NPM_TOKEN secret + provenance) Nitpick: - Single-char term filter (t.length > 1) kept intentionally — prevents noise from single-letter matches; documented in AGENTS.md if needed 581 tests passing * fix(ci): add --legacy-peer-deps for zod v3/v4 peer conflict @anthropic-ai/claude-agent-sdk@0.2.56 requires zod@^4.0.0 as a peer dependency but the project uses zod@^3.23.0. The lock file resolves this locally but npm ci is strict about peer deps in CI. * fix(ci): drop Node 18 from matrix — tsdown requires Node 20+ tsdown/rolldown uses node:util.styleText which is only available in Node 20.12+. Updated engines field to >=20.0.0 to match. * fix(ci): add inlineOnly: false to tsdown config, target node20 tsdown errors on CI with "Consider adding inlineOnly option" when dependencies are bundled. Setting inlineOnly: false suppresses this. Also updated target from node18 to node20 to match engines field. |
||
|
|
fa608ed29e |
fix: add missing name/owner fields to marketplace.json (#75) (#81)
marketplace.json was missing required top-level name and owner fields, and plugins[].source was incorrectly named path. Fixes plugin install validation error in Claude Code. |
||
|
|
c248e6b042 |
fix: resolve 6 issues — performance, scheduling, TTL, plugin (#28 #29 #30 #36 #63 #75) (#78)
Performance: - auto-forget.ts (#29): concept-bucketed contradiction detection with pre-tokenized cache, O(n * avg_bucket) instead of O(n^2) - consolidate.ts (#28): cap LLM calls at 10, process largest concept groups first - vector-index.ts (#30): bounded min-heap search replaces full sort, early skip for low-scoring entries Scheduling (#36): - index.ts: setInterval auto-forget (1h default) and consolidation (2h, opt-in via CONSOLIDATION_ENABLED=true) - Configurable via AUTO_FORGET_INTERVAL_MS, CONSOLIDATION_INTERVAL_MS - Timers use .unref() to not prevent process exit Memory TTL (#63): - remember.ts: optional ttlDays parameter auto-sets forgetAfter Plugin (#75): - plugin.json: version 0.2.0 -> 0.6.0 Closes #28 #29 #30 #36 #63 #75 |
||
|
|
857f71e3c6 |
feat: v0.6.0 advanced retrieval with real-world benchmarks (#76)
* feat: add 9 orchestration modules for v0.5.0 Add actions, frontier, leases, routines, signals, checkpoints, flow-compress, mesh, and branch-aware modules with full MCP tools, REST endpoints, and 170 new tests. Includes SSRF protection, race-condition-safe keyed mutex locking, SHA-256 fingerprinting, and fixes for 29 CodeRabbit review findings. - 9 new source files (src/functions/*) - 8 new test files (170 tests, total 386) - 10 new MCP tools, 23 new REST endpoints - 8 new KV scopes, new types for orchestration - Version bump to 0.5.0, README and viewer updated * feat: add sentinels, sketches, crystallize, diagnostics, facets modules 5 new modules inspired by beads patterns but with original naming and iii-engine real-time streaming (no polling): - sentinels: event-driven condition watchers (webhook, timer, threshold, pattern, approval) that auto-unblock gated actions via SSE - sketches: ephemeral action graphs with auto-expiry, promote or discard - crystallize: LLM-powered compaction of completed action chains into compact crystal digests with key outcomes and lessons - diagnostics: self-diagnosis across 8 categories (actions, leases, sentinels, sketches, signals, sessions, memories, mesh) with auto-heal - facets: multi-dimensional tagging (dimension:value) with AND/OR queries - 5 new source files, 5 new test files (132 tests, total 518) - 9 new MCP tools (total 37), 21 new REST endpoints (total 93) - 4 new KV scopes (total 33), new types for all modules - README stats and function table updated * fix: address code review findings across v0.5.0 modules - actions: validate edges before persisting, set blocked status for requires deps - leases: use mem:action lock key, reject blocked actions, check expiry on release - checkpoints: validate linkedActionIds exist, check requires edges in unblock - mesh: add SSRF validation on peer registration - routines: remove invalid "failed" action status check - export-import: add v0.5.0 scope export/import (actions, sentinels, sketches, etc) - mcp/server: validate CSV inputs are strings before splitting - schema: replace runtime require with static import - README: fix stale tool/endpoint counts (28→37, 72→93) * fix: second round code review — mesh locks, routines DAG, MCP input validation, README counts - mesh.ts: add withKeyedLock on action writes in receive path, add IPv6 private ranges to SSRF check - routines.ts: validate DAG (duplicate orders, unknown deps), set dep actions to blocked, refresh stepStatus in routine-status - checkpoints.ts: runtime type enum validation, set linked pending actions to blocked - leases.ts: validate ttlMs is finite positive number - export-import.ts: add skip strategy checks for all v0.5.0 import blocks - mcp/server.ts: typeof guards on tags, config JSON.parse, actionIds, linkedActionIds, categories - README.md: Tools 18→37, Functions 33→50, stats line updated - test: update checkpoint test for new blocked-on-create behavior * fix: third round review — lease renew/release safety, mesh locking, export replace cleanup, MCP input guards - leases.ts: renew extends from max(now, existing expiry) instead of now; release verifies action ownership before mutation - mesh.ts: withKeyedLock on memory writes in mesh-receive; applySyncData validates id/updatedAt and locks both memory and action writes - routines.ts: stepStatus maps "blocked" to "pending" explicitly; progress includes blocked/cancelled counts; routine-freeze wrapped in withKeyedLock - export-import.ts: remove unused RoutineRun import; replace strategy clears all orchestration namespaces; skip strategy for graphNodes/graphEdges/semantic/procedural - mcp/server.ts: sentinel_trigger JSON.parse with typeof+try/catch; facet_query typeof guards on matchAll/matchAny; remove redundant requires cast; .filter(Boolean) on concepts/files/tags/requires CSV splits - README.md: clarify API table is a representative subset * fix: fourth round review — redirect SSRF, blocked-on-create, missing action handling, boolean normalization - mesh.ts: add redirect:"error" to both outbound fetch calls to prevent SSRF via redirect - routines.ts: create actions with status "blocked" directly when hasDeps (eliminates two-pass race); handle missing actions in routine-status as cancelled; progress.total uses run.actionIds.length - mcp/server.ts: sentinel config accepts object values directly; normalize unreadOnly/dryRun for both JSON booleans and string values - README.md: consistent bundle size (365KB) across both occurrences * feat: v0.6.0 advanced retrieval — triple-stream search, stemming, real benchmarks Search improvements: - Porter stemmer for word normalization (authentication ↔ authenticating) - 40+ coding-domain synonym groups (db ↔ database, k8s ↔ kubernetes) - Binary-search prefix matching replaces O(n) full scan - Session diversification (max 3 results per session) - Co-occurrence graph edges between all concept pairs New retrieval modules: - Sliding window inference pipeline (context enrichment at ingestion) - Adaptive query expansion (LLM-generated reformulations) - Triple-stream search (BM25 + Vector + Graph with RRF fusion) - Append-only temporal knowledge graph (versioned edges, point-in-time queries) - Graph-augmented retrieval (entity search + neighborhood expansion) - Ebbinghaus retention scoring (decay + tiered hot/warm/cold/evictable) Real-world benchmarks (240 observations, 20 labeled queries): - Quality eval: 64.1% recall@10 with Xenova embeddings (vs 55.8% grep) - Scale eval: 92-100% token savings vs built-in memory at 240-50K observations - Cross-session: 12/12 queries found vs 10/12 for 200-line MEMORY.md cap - Token measurement uses actual search results (fixed fake constant bug) - Removed old microbenchmarks (bench.ts, run-bench.ts, COMPARISON.md) |
||
|
|
709905696b |
fix: package.json paths, standalone shebang, integration tests
- Fix main/bin/start to use .mjs extension (tsdown outputs ESM) - Remove duplicate shebang banner from standalone build config - Update integration test: health status "healthy" (v0.4.0), viewer HTML check - Add POST body to pre-compact hook for claude-bridge sync |
||
|
|
134cf96124 |
feat: agentmemory v0.4.0 — the memory layer for all AI coding agents (#9)
* feat: agentmemory v0.4.0 — the memory layer for all AI coding agents 7 new features: Claude Code memory bridge, standalone cross-agent MCP server, knowledge graph with entity extraction, 4-tier memory consolidation pipeline, team/shared memory, memory governance with audit trail, git-versioned snapshots. 33 functions, 18 MCP tools, 6 MCP resources, 3 MCP prompts, 49 REST endpoints, 21 KV scopes, 216 tests. All features opt-in via env vars. * fix: address 28 CodeRabbit findings across v0.4.0 codebase Critical: Fix bin path mismatch (dist/mcp-standalone.mjs -> dist/standalone.mjs) Bugs: Fix procedural decay, parseFloat||0.5 for zero values, snapshot restore missing graphNodes/observations, git catch too broad, N+1 graph query, BFS duplicate edges, array mutation in audit sort, date validation Improvements: Lazy readline in transport, JSON-RPC validation, persist error handling, ID collision prevention, defensive null coalescing for concepts/files, Windows backslash support in config, direction required for bridge sync tool, try-catch for audit/governance MCP, team profile fallback teamId, POST body for bridge sync hook, observations validation for graph-extract endpoint, await in test |
||
|
|
8b21ae2bf6 |
feat: agentmemory v0.4.0 — MCP resources, prompts, enrichment, confidence (#7)
* feat: agentmemory v0.4.0 — MCP resources, prompts, enrichment, confidence Add 4 MCP resources (status, project profile, recent sessions, latest memories), 3 MCP prompts (recall_context, session_handoff, detect_patterns), confidence-scored memory relations, and a unified enrich endpoint that aggregates file context, relevant observations, and past bug memories for PreToolUse hook injection. - Add confidence field to MemoryRelation with auto-scoring from co-occurrence, recency, and relation type - Add mem::enrich function aggregating 3 sources with resilient .catch() fallbacks - Add POST /agentmemory/enrich REST endpoint - Switch PreToolUse hook from file-context to enrich endpoint with search term extraction - Add minConfidence filter and confidence-desc sorting to mem::get-related - 27 new tests (171 total), all passing * fix: address review findings — input validation, XML escaping, confidence scoring - enrich.ts: Sort bug memories by recency before slicing top 3; add escapeXml() for narratives and bug content injected into XML tags - relations.ts: Use filter+max instead of find() for matchingRelation to pick highest confidence when multiple edges exist; normalize minConfidence with Number.isFinite + clamp to [0,1] - mcp/server.ts: Guard decodeURIComponent with try/catch returning 400 on malformed percent-encoding; use typeof checks for prompt args instead of truthy checks; normalize minConfidence/maxHops at MCP layer - api.ts: Validate files[] and terms[] element types are strings before calling mem::enrich - Tests: Add malformed URI and non-string prompt arg test cases (173 total) |
||
|
|
0e9d5ac76f |
fix: address 12 code review findings across validation, safety, and correctness
- observe.ts: extract fields from sanitizedRaw instead of payload.data - mcp/server.ts: add input validation per tool and try-catch error boundary - api.ts: validate request bodies for /remember, /forget, /migrate - post-tool-failure.ts: truncate tool_input and error to 4000 chars - pre-tool-use.ts: skip "pattern" key for Grep (regex, not file path) - recall/SKILL.md: escape $ARGUMENTS before injecting into curl JSON - consolidate.ts: use ?? instead of || for minObservations, add 30s timeout - file-index.ts: filter sessions by project, cache observations per session - patterns.ts: remove 80-char truncation on error keys - remember.ts: validate content non-empty, skip empty observationIds - index.ts: add missing /generate-rules log line - subagent-stop.ts: normalize timeout to 2000ms |
||
|
|
45795b6033 |
feat: v0.2.0 -- full memory upgrade with 12 hooks, MCP tools, skills, and intelligence
New hooks (7): - PreToolUse: inject file history before edits (Edit/Write/Read/Glob/Grep) - PostToolUseFailure: capture error patterns for learning - PreCompact: preserve memory context through compaction - SubagentStart/SubagentStop: track multi-agent workflows - Notification: capture permission prompts (tool preferences) - TaskCompleted: track team task completions New functions (4): - mem::file-context: file-centric memory index for PreToolUse - mem::consolidate: merge observations into long-term memories via LLM - mem::patterns + mem::generate-rules: detect co-change patterns and recurring errors - mem::remember + mem::forget: explicit save/delete for long-term memory MCP server (2 endpoints): - GET /agentmemory/mcp/tools: list 5 MCP tools (recall, save, file_history, patterns, sessions) - POST /agentmemory/mcp/call: dispatch tool calls to iii functions Skills (4): - /recall [query]: search past observations - /remember [insight]: save to long-term memory - /session-history: show past session timeline - /forget [target]: delete specific memory data New API endpoints (7): - POST /agentmemory/file-context - POST /agentmemory/remember - POST /agentmemory/forget - POST /agentmemory/consolidate - POST /agentmemory/patterns - POST /agentmemory/generate-rules - GET/POST /agentmemory/mcp/* Updated: types (7 new HookTypes, 3 new ObservationTypes), version 0.2.0 |
||
|
|
4c334b0a0e |
fix: system audit -- 10 bugs found and resolved
1. events.ts: Event triggers were calling api:: functions which require ApiRequest shape and auth headers. Rewrote to call core functions (kv.set, sdk.trigger) directly, bypassing auth. 2. All 5 hooks: Missing AGENTMEMORY_SECRET auth header. If secret was set, every hook would get 401 from the API. Now all hooks read AGENTMEMORY_SECRET and send Bearer token. 3. observe.ts: stripPrivateData on JSON string could break JSON structure when replacement text differs in length. Added try/catch fallback to string coercion. 4. post-tool-use.ts: truncate() for objects did JSON.parse(str.slice(0, max-1) + '}') which produces invalid JSON in nearly all cases. Changed to return truncated string. 5. compress.ts: LLM-returned importance was not clamped to 1-10 range. Added Math.max(1, Math.min(10, ...)) with NaN fallback. 6. compress.ts: LLM-returned observation type was not validated against ObservationType union. Invalid types now fall back to "other". 7. context.ts: Token estimate for observation blocks only counted inner content, not the "## Session..." header. Fixed to estimate the full block text. 8. viewer: WebSocket port now configurable via ?wsPort= query param for non-default III_STREAMS_PORT configurations. 9. plugin/scripts: Rebuilt with auth header support matching the updated hook source files. |
||
|
|
6df02d3e20 |
add plugin marketplace install support
- Add .claude-plugin/marketplace.json for /plugin marketplace add
- Build hook scripts into plugin/scripts/ (self-contained)
- Fix hooks.json to use ${CLAUDE_PLUGIN_ROOT} paths
- Update README with plugin install as primary quick start
|
||
|
|
37de9e5d02 | feat: agentmemory v0.1.0 -- persistent memory for AI coding agents |