Commit Graph

485 Commits

Author SHA1 Message Date
Rohit Ghumare 7ee6c70a73 docs: governance baseline for AAIF project proposal
Adds the governance / contribution / lifecycle documentation required
by aaif.io's Project Lifecycle Policy and their proposal template.

New files:
- GOVERNANCE.md — LF Minimum Viable Governance pattern scoped to the
  project's current single-maintainer state, with explicit process for
  adding Maintainers, lazy-consensus PR flow, and non-PR decision path
  via 'governance'-labeled issues.
- CONTRIBUTING.md — fork/branch naming, Node requirements, local build
  + test expectations, DCO sign-off, PR flow, subsystem cheat-sheet,
  step-by-step guidance for adding MCP tools and hooks, release
  process summary.
- MAINTAINERS.md — current Maintainer roster (just me for now), an
  Emeritus section, and named notable contributors in line for future
  Maintainer review.
- ROADMAP.md — 12 months of planned work through Q1 2027, split into
  quarterly themes (Depth / Breadth / Trust / v1.0) with shipped /
  active / planned / candidate buckets per quarter.
- CODE_OF_CONDUCT.md — Contributor Covenant 2.1 with the enforcement
  path pointing at the Maintainer email.
- SECURITY.md — vulnerability reporting flow via GitHub Security
  Advisories, supported-version policy, scope, safe-harbor clause,
  and a pointer to the .github/security-advisories/ drafts.
- .github/AAIF-PROPOSAL-DRAFT.md — paste-ready answers for every
  required field on the aaif/project-proposals issue template,
  targeted at Growth Stage entry.

No code changes.
2026-04-18 20:28:45 +01:00
Rohit Ghumare b99c9ec5d6 feat(website): derive version + MCP/hook/REST counts from source at build
Website chip + stats + terminal + features were hardcoded to 0.8.13,
44, 12, 49 — they drifted every release. Now every one of them is
read at build time from the real source of truth:

- lib/meta.ts (server-only) reads package.json, src/triggers/api.ts
  (api_path count), src/mcp/tools-registry.ts (memory_* name count),
  and the HookType union in src/types.ts.
- Hero chip, Stats, LiveTerminal, and Features all consume the
  computed counts via props; no more literal strings in component
  bodies.
- Fallback defaults (44 / 12 / 49) kick in only if the source files
  cannot be read, so a monorepo re-root still boots.

Result: cutting a release bumps the website hero to v<new>
automatically, and any new MCP tool or REST endpoint raises the
displayed count without an edit.

next build stays clean — single static page prerendered.
2026-04-18 20:19:33 +01:00
Rohit Ghumare ba39a18d53 Merge pull request #166 from rohitg00/ci/publish-fs-watcher
ci(publish): add @agentmemory/fs-watcher to the release workflow
2026-04-18 20:05:58 +01:00
Rohit Ghumare 3ed85ffaec ci(publish): add @agentmemory/fs-watcher to the release workflow
Ships the new filesystem connector to npm on every release.
Also adds workflow_dispatch so we can manually publish packages
without cutting a release — useful for back-filling fs-watcher
against v0.9.0 which merged before the workflow knew about it.
2026-04-18 20:04:21 +01:00
Rohit Ghumare 4109e4e97d Merge pull request #165 from rohitg00/release/v0.9.0
chore: release v0.9.0
v0.9.0
2026-04-18 20:01:22 +01:00
Rohit Ghumare 3862c3f0d4 chore: release v0.9.0
Bump version + ship CHANGELOG covering everything that merged since
v0.8.13:

- #118 security advisory drafts for v0.8.2 CVEs
- #132 semantic eviction routing + batched retention audit
- #157 iii console docs + vendored screenshots in README
- #160 (#158) health gated on RSS floor
- #161 (#159) standalone MCP proxies to the running server
- #162 (#125) mem::forget audit coverage + policy doc
- #163 (#62) @agentmemory/fs-watcher filesystem connector
- #164 Next.js website (website/ root, ship to Vercel)

Version bumps (8 files):
- package.json / package-lock.json (top + packages[''])
- plugin/.claude-plugin/plugin.json
- packages/mcp/package.json (self + ~0.9.0 dep pin)
- src/version.ts (union extended, assigned 0.9.0)
- src/types.ts (ExportData.version union)
- src/functions/export-import.ts (supportedVersions set)
- test/export-import.test.ts (export assertion)

Tests: 777 passing. Build clean.
2026-04-18 20:00:26 +01:00
Rohit Ghumare 4e7d0007e3 Merge pull request #164 from rohitg00/feat/website-lambo
feat(website): lamborghini-inspired landing page
2026-04-18 19:52:20 +01:00
Rohit Ghumare 3338f9d039 feat(website): live GitHub stars, logo-based agent showcase, simpler MCP install
Nav
- Replace overlay hamburger with a solid horizontal bar.
- Use the real agentmemory icon from assets/icon.svg as the brand mark.
- Single GitHub pill: GH icon + GITHUB label + gold star + live count,
  the entire pill links to the repo. No more separate icon button.
- Server-rendered count pulled from api.github.com/repos/... with
  revalidate 3600. Falls back to 0 on rate limit.
- Mobile (<720px) collapses to a hamburger sheet with sections + links.

Command Center (new)
- Tabbed section showing the shipped viewer (:3113), the iii console
  (:3114), the raw KV state browser, and OTel traces.
- Real screenshots vendored into public/ (dashboard.png,
  states.png, traces-waterfall.png, demo.gif).
- Each tab ships with a description, 4-5 capability bullets, and a
  copy-ready launch command.

Features (new)
- 12-tile grid covering 12 auto-hooks, 44 MCP tools, 49 REST
  endpoints, BM25+vector+graph recall, auto consolidation, JSONL
  replay, knowledge graph extraction, mesh federation, Obsidian
  export, 5 LLM providers, OTel observability, 0 external DBs.

Agents
- Replaced the flat tile grid with an agents.md-style two-tier layout.
- Top row: 4 featured first-party integrations (Claude Code,
  OpenClaw, Hermes, Codex CLI) as big cards with real logos, brand
  accent colors, and integration pitch.
- Bottom row: CSS keyframe marquee of every other supported agent
  (Claude Desktop, Cursor, Gemini CLI, OpenCode, Cline, Roo,
  Kilo, Goose, Aider, Windsurf) with real logos + brand borders on
  hover. Pauses on hover. Edges fade into the page. Respects
  prefers-reduced-motion.

Install · step 3 · MCP wiring
- Dropped the 10-tab toggle and the Cursor-only gold hero button.
- Left column: equal-weight agent chips in a 2x3 grid — Cursor,
  VS Code, Claude Code, Claude Desktop, Gemini CLI, Codex CLI.
  Click copies the right snippet (JSON / CLI command / TOML) or
  fires the one-click deeplink where one exists.
- Right column: UNIVERSAL MCP JSON — paste-ready block that works
  for Claude Desktop, Cursor, Cline, Windsurf, Gemini CLI, OpenCode.
- Expando reveals Hermes, OpenClaw, and Codex TOML shapes.

Infrastructure
- lib/github.ts server-only fetch for repo stats.
- lib/format.ts (client-safe) formatCompact.
- next.config.ts: turbopack.root pinned to silence workspace warning,
  images.remotePatterns for github.com / GH avatars / Cursor /
  Windsurf logos.
- layout.tsx: icon metadata wired to /icon.svg.

Build: next build clean, 3 routes prerendered static, 0 vulns.
2026-04-18 19:50:59 +01:00
Rohit Ghumare 7193361b67 refactor(website): rebuild as Next.js 16 App Router app for Vercel
Replaces the vanilla HTML/CSS/JS landing with a production Next.js 16.2
app router build. Deploy target is Vercel; root directory should be
set to 'website/' in the Vercel project settings.

Stack:
- Next.js 16.2 + React 19 + TypeScript 5.7
- next/font for Archivo + JetBrains Mono (no external fetch)
- CSS Modules per component + one globals.css for tokens
- No Tailwind, no bundler config, no client-side routing

Component layout:
- app/layout.tsx           — <html>, font vars, metadata, viewport
- app/page.tsx             — composes all landing sections
- app/globals.css          — design tokens + shared utilities
- components/Nav.tsx       — hexagonal bull mark + menu
- components/Hero.tsx      — title, lede, CTAs
- components/MemoryGraph.tsx   — client canvas animation + hex pause
- components/ScrollProgress.tsx — fixed top gold progress rail
- components/Stats.tsx     — counter-up on first intersect
- components/Primitives.tsx — three cards with 3D mouse tilt
- components/LiveTerminal.tsx  — typewriter memory.recall demo
- components/Compare.tsx   — vs Mem0/Letta/Cognee table
- components/Agents.tsx    — supported-agents grid
- components/Install.tsx   — click-to-copy npm + console boxes
- components/Footer.tsx    — source / changelog / license links

Interactive elements are "use client" islands; static sections render
on the server. prefers-reduced-motion gated throughout.

Upgraded Next from 15.1.3 to 16.2.4 to clear CVE-2025-66478 during
setup. next build completes clean, all 3 routes prerender static.

Deploy:
  1. Import repo on Vercel, set Root Directory = website/
  2. Or: cd website && npx vercel
2026-04-18 19:15:11 +01:00
Rohit Ghumare 8db6da43d7 feat(website): lamborghini-inspired landing page
Single-page marketing site for agentmemory generated from the
getdesign@latest 'lamborghini' design system.

- DESIGN.md at repo root: the full 288-line design brief (black canvas,
  gold accent, Neo-Grotesk display, zero border-radius, hexagonal
  motifs). Future UI PRs should read this file first.
- website/index.html: hero + stats + primitives + live terminal +
  competitor comparison + agents grid + install + footer.
- website/styles.css: black-first palette (#000 canvas, #FFC000
  accent, #202020 surface), Archivo display at 160px hero, JetBrains
  Mono for the terminal, sharp-edge buttons, reveal-on-intersect.
- website/script.js: vanilla, zero deps.
  - animated canvas memory graph in the hero with a hexagonal pause
    control
  - stat counters that run on first intersect
  - 3D mouse-tilt on primitive cards
  - typewriter terminal demo of memory.recall and memory.consolidate
    with a REPLAY button
  - click-to-copy install boxes with success feedback
  - top scroll progress rail in gold
  - full prefers-reduced-motion short-circuit

No framework, no build step. Drop behind any static host.
2026-04-18 19:06:58 +01:00
Rohit Ghumare 018e2e7b8c Merge pull request #163 from rohitg00/feat/62-filesystem-watcher
feat: filesystem connector — emits observations on file changes
2026-04-18 18:46:38 +01:00
Rohit Ghumare 02ebc5f1fa fix(fs-watcher): address CodeRabbit review
Three issues flagged by review.

1. CRITICAL - observe endpoint rejects current payload shape. The
   /agentmemory/observe handler requires a full HookPayload (non-empty
   hookType from the fixed HookType union, sessionId, project, cwd,
   timestamp) with observation data under 'data'. The watcher was
   emitting hookType='file_change'/'file_delete' (not valid HookType
   values), possibly-null sessionId and project, no cwd or timestamp,
   and files/content/metadata at the top level. The server would 400
   every observation.

   Now emits hookType='post_tool_use' with changeKind moved into
   data.changeKind. sessionId auto-generates as
   fs-watcher-<ts>-<rand> when not supplied; project defaults to the
   first watched directory's basename. cwd is set to the root that
   triggered the event, timestamp to new Date().toISOString().
   files/content/rootDir/absPath/size/truncated/source all sit under
   data.

2. MAJOR - start() returned successfully even when every fs.watch call
   failed. In CLI/supervisor usage that looked like a healthy start
   while no observations ever fired. Now start() throws if
   this.watchers ends up empty, with the node-version hint in the
   message since Node 18 + Linux is the likely cause.

3. MAJOR - engines.node was >=18, but fs.watch(recursive: true) on
   Linux only landed in Node 19.1.0. Raised to >=20 (next LTS after
   19.x) and documented the requirement in README.

test/fs-watcher.test.ts:
- Updated two shape assertions (hookType, sessionId, project, cwd,
  timestamp at top level; files/content/changeKind under data).
- Added test that start() throws when no roots can be watched.
2026-04-18 18:40:36 +01:00
Rohit Ghumare 61cdaf600a Merge pull request #162 from rohitg00/fix/125-audit-coverage
fix(audit): add audit coverage for mem::forget + document policy
2026-04-18 18:39:00 +01:00
Rohit Ghumare ef002195d6 docs(audit): clarify mem::auto-forget is bulk, not user-initiated (CR) 2026-04-18 18:38:00 +01:00
Rohit Ghumare bfcff26cc1 feat: filesystem connector — emits observations on file changes (#62)
First of the data-source connectors tracked in #62. Ships as
@agentmemory/fs-watcher under integrations/filesystem-watcher/.

Scope (v0.1.0):
- Watches one or more roots via node:fs.watch({recursive: true}).
  No native deps; works on macOS / Linux / Windows 10+.
- Emits file_change / file_delete observations to
  POST /agentmemory/observe on the running server.
- Debounces 500ms per path so a stream of editor saves collapses
  to a single observation.
- Reads the first 4 KB of text files for content preview;
  truncation is flagged in metadata. Binary files are skipped by
  default (AGENTMEMORY_FS_WATCH_ALLOW_BINARY=1 to opt in).
- Default ignore set: .git, node_modules, dist, build, .next,
  .turbo, coverage, .DS_Store, *.log, *.lock. Extensible via
  AGENTMEMORY_FS_WATCH_IGNORE.
- Attaches Bearer AGENTMEMORY_SECRET when set.
- CLI and env-driven config; CLI args win. Can be supervised with
  launchd / systemd / pm2.

Tests (test/fs-watcher.test.ts):
- file_change on write, file_delete on unlink.
- Default ignore set skips node_modules/.
- Bearer auth header attached when secret is configured.
- Debounce collapses four rapid writes to <=2 observations.
- configFromEnv parses dirs and regex ignore patterns.

GitHub and Slack connectors (from #62) will be separate PRs since
they need OAuth / token handling and a shared event-normalizer;
the file-watcher has no such dependency and is useful standalone.
2026-04-18 13:05:13 +01:00
Rohit Ghumare 9a66804338 fix(audit): add audit coverage for mem::forget + document policy (#125)
Addresses issue #125's policy question.

Decision adopted (hybrid of Options A and C):
- EVERY structural deletion must call recordAudit. Silent deletes
  are forbidden.
- Scoped deletions (governance-delete, forget) emit one audit row
  per call with targetIds populated.
- Bulk sweeps (retention-evict, evict, auto-forget) emit one
  batched audit row per invocation with targetIds listing every
  removed id, to avoid flooding the log during routine sweeps.

Implementation gap closed: mem::forget previously deleted memories,
observations, sessions, and summaries without ever calling
recordAudit. Added a single batched audit row per invocation with
sessionId, counts by type, and sessionDeleted flag.

Policy comment added to src/functions/audit.ts so new deletion
sites have an explicit precedent instead of discovering it via
review cycles.

Test coverage (test/remember-forget-audit.test.ts):
- Single-memory forget: one audit row, targetIds=[memId], forget op.
- Whole-session forget: one audit row batching all observation ids,
  sessionDeleted=true, deleted count sums memories+observations+2.
- No-op forget (neither memoryId nor sessionId): no audit row.

All 769 existing tests still pass.
2026-04-18 12:57:15 +01:00
Rohit Ghumare 78aefcefea Merge pull request #132 from Tanmay-008/fix/semantic-memory-eviction
fix: route semantic memory eviction to correct KV store using source …
2026-04-18 12:52:36 +01:00
Rohit Ghumare a9889e689c Merge pull request #118 from rohitg00/docs/security-advisories-v082
docs: v0.8.2 security advisory drafts
2026-04-18 12:52:33 +01:00
Rohit Ghumare 8207502328 Merge main into fix/semantic-memory-eviction
Resolve conflicts introduced by subsequent main commits touching the
same retention paths:

- types.ts: union the AuditEntry operation set — keep main's superset
  (adds relation_create/relation_update/retention_score/skill_extract/
  core_add/core_remove/auto_page). Drop HEAD's duplicate source key
  on RetentionScore (already present).
- functions/retention.ts: keep main's cleaner score assembly that
  uses pre-computed temporalDecay / reinforcementBoost / logs-based
  lastAccessed and accessCount. Keep main's evictedIds /
  evictedEpisodic / evictedSemantic counters. Adopt main's batched
  audit emission (single record per invocation with reason) from
  after the loop — HEAD's per-candidate audit emission fails the
  'single batched audit record' test and would also flood the audit
  log during normal eviction sweeps. Preserve HEAD's null-guarded
  continue when neither the episodic nor the semantic store has the
  candidate, so legacy rows with a missing source field still evict
  cleanly without a spurious delete against the wrong scope.
- test/retention.test.ts: drop HEAD's smaller test in favor of
  main's more comprehensive suite (scores tag rows with source /
  evicts from mem:semantic / batched audit on success / no audit
  when evicted=0 / score emits per-rescore audit / probes namespaces
  for legacy semantic rows / routes legacy missing-source episodic
  rows to mem:memories). Main's suite is a strict superset of HEAD's
  original assertion.
2026-04-18 12:25:34 +01:00
Rohit Ghumare a4a1d23d12 docs: address CodeRabbit review on security advisory drafts
- 04-mesh-unauth.md: correct 4->5 mesh REST endpoints in patch summary.
- 05-obsidian-export-traversal.md: document the known symlink-traversal
  limitation of resolveVaultDir(). The 0.8.2 fix uses lexical containment
  only (path.resolve + startsWith) and does not call realpath/lstat, so a
  pre-existing symlink under AGENTMEMORY_EXPORT_ROOT pointing outside the
  root is still a viable escape. Advisory now names this explicitly and
  points users at sandboxing or a follow-up issue for full hardening.
2026-04-18 12:22:05 +01:00
Rohit Ghumare 3037dd27f8 Merge pull request #160 from rohitg00/fix/158-health-rss-gate
fix(health): gate memory severity on RSS floor
2026-04-18 11:46:29 +01:00
Rohit Ghumare 1cd8a0a409 Merge pull request #161 from rohitg00/fix/159-mcp-proxy
fix(mcp): proxy standalone tools to running server when reachable
2026-04-18 11:46:17 +01:00
Rohit Ghumare 8f2e14ce9c fix(mcp): address CodeRabbit review on standalone proxy
Four issues flagged by review.

1. Handle cache was never invalidated. Once resolveHandle() set
   cached = local, a later server start would never be picked up
   until the process restarted. Add invalidateHandle() + a 30s TTL
   on local-mode caching so the next call after proxy failure or
   timeout re-probes.

2. Response shapes diverged between proxy and local. memory_recall
   and memory_smart_search returned { mode, query, results } from
   the server but Memory[] from local; memory_audit returned an
   array from local and whatever the server sent from proxy.
   Normalize local responses to server-shaped envelopes
   ({ mode: compact, results: [...] } and { entries: [...] }) so
   a per-request fallback no longer flips structure under the caller.

3. Validation errors from handleProxy were logged as 'proxy call
   failed' and then retried against local, which re-threw the same
   validation error. Extract validate(toolName, args) and run it
   once before mode resolution, so empty content/query/memoryIds
   throw cleanly with no misleading stderr line.

4. Bearer-token test was vacuous — seen.every() passes trivially
   on an empty list and only the probe was guaranteed to record.
   Replace with a Map<path, auth> assertion that pins both the
   probe at /livez and the proxied tool call at /sessions to
   Bearer s3cret.

Updates test/mcp-standalone.test.ts to match the new local
response shape (previously asserted raw Memory[] length, now
asserts results.length).
2026-04-18 11:39:32 +01:00
Rohit Ghumare 0f09e97e3c fix(health): emit heap_tight alert in warn band too, not only critical
CodeRabbit flagged that the 'visibility without inflating severity'
goal was only met at critical-level heap. When heap sat in the warn
band (80-95%) with RSS below the floor, no alert was produced at
all, so operators got zero signal that heap pressure was building.

Widen the heap_tight branch to cover the full memoryWarnPercent+
band. New test: 85%% heap / 50 MB RSS stays healthy but records
memory_heap_tight_*.
2026-04-18 11:35:40 +01:00
Rohit Ghumare 7ef6155806 fix(mcp): proxy standalone tools to running server when reachable (#159)
Previously @agentmemory/mcp's handleToolCall only ever used a local
InMemoryKV, so in the supported Claude Code setup (plugin +
@agentmemory/agentmemory server) the MCP tools never saw the data
hooks had captured — memory_sessions returned [] even when the REST
endpoint had 69 observations, memory_smart_search searched a
standalone.json that only contained explicit memory_save calls, and
the server's BM25 + vector + graph indexing was inaccessible through
MCP.

Now handleToolCall resolves a Handle once per process: if a server
responds to GET /agentmemory/livez within 500ms, all subsequent tool
calls route through the REST endpoints and see exactly what hooks and
the viewer see. If the probe fails, the caller falls back to the
existing local InMemoryKV path so users who run MCP alone still work.

- New src/mcp/rest-proxy.ts: probe + cached Handle with 15s call
  timeout. Honours AGENTMEMORY_URL (defaults to http://localhost:3111)
  and attaches Bearer AGENTMEMORY_SECRET when set.
- src/mcp/standalone.ts: split handleProxy and handleLocal branches;
  announce active mode once to stderr so users can see which store
  their tools are reading. On per-request proxy failure, log and
  fall back to local KV for that single call.
- test/mcp-standalone-proxy.test.ts: five cases covering proxy happy
  path, auth header, unreachable server fallback, and post-probe
  proxy failure fallback.
2026-04-18 11:23:59 +01:00
Rohit Ghumare c57acd7f93 fix(health): gate memory severity on RSS floor (#158)
Previously heapUsed/heapTotal ratio alone decided memory severity, so
a small steady-state Node process whose V8 heap naturally fills its
46 MB allocation could report memory_critical_97% while the RSS sat
at 120 MB and the host had plenty of free RAM.

Require a second signal before degrading overall health: heap ratio
above threshold AND RSS above memoryRssFloorBytes (default 512 MB).
When heap is tight but RSS is below the floor, record a non-alerting
memory_heap_tight_NN% note so the info is still visible in the
snapshot without inflating status to degraded/critical.

New tests cover the reporter's live-deployment example plus the
critical / degraded / healthy branches around the RSS floor.
2026-04-18 11:21:40 +01:00
Rohit Ghumare 329e7ca082 Merge pull request #157 from rohitg00/docs/iii-console-readme
docs: document iii console for trace-level inspection
2026-04-17 17:34:42 +01:00
Rohit Ghumare 75c994dc43 Update README.md 2026-04-17 17:34:30 +01:00
Rohit Ghumare d87cfa6921 docs: embed iii console screenshots in README
Add two screenshots sourced from iii.dev/docs/console and vendored into
assets/iii-console/ so they don't depend on CDN signed URLs:

- dashboard.png — hero shot showing counters, application flow, and
  registered triggers.
- traces-waterfall.png — trace waterfall with per-span durations,
  placed above the traces setup block.

states.png is checked in for a future edit but not yet referenced.
2026-04-17 17:31:58 +01:00
Rohit Ghumare ebacb20b13 docs: document iii console for trace-level inspection
agentmemory runs on the iii engine, so the official iii console gives
users OTEL traces, the raw KV state browser, the stream monitor, and a
direct function invoker for every piece of memory machinery without
wiring up MCP or a custom client.

- Install and launch instructions, with --port 3114 to avoid the
  agentmemory viewer already holding 3113.
- Page-by-page guide covering Functions, Triggers, States, Streams,
  Traces, and Logs with agentmemory-specific use cases.
- Notes that the iii-observability worker is already enabled in
  iii-config.yaml with exporter: memory, so Traces and Logs light
  up by default.
- Warns that the console has no built-in auth and must stay on
  127.0.0.1.
2026-04-17 17:24:57 +01:00
Rohit Ghumare 0e8157eaa6 Update README.md 2026-04-17 13:16:22 +01:00
Rohit Ghumare 6b129dd51f Merge pull request #155 from rohitg00/feat/replay-tab
feat: session replay tab + JSONL transcript import
2026-04-17 13:15:30 +01:00
Rohit Ghumare 50817adb8a fix: address CodeRabbit review on session replay
Security:
- Tighten sensitive-path guard to boundary-aware regexes (no more
  false positive on project names containing "token", "secret", etc.)
- Re-check every walked JSONL file against the guard, not just the
  root argument
- Expand leading "~" in user-supplied paths before resolve()

Correctness:
- Update existing Session.observationCount on re-import instead of
  silently leaving it stale
- Parallelize per-session observation writes via Promise.all
- Capture a single fallback timestamp in the parser so startedAt and
  endedAt agree when metadata is missing
- Trim incoming path in the import REST handler

Robustness:
- Add AbortSignal.timeout(120s) to the CLI import fetch and surface
  TimeoutError cleanly
- Stop the replay interval when switching away from the replay tab
- Style the Replay tab empty state with a new .empty rule

Sync:
- Bump REST endpoint count (104 -> 107) in startup banner + README
- Add 0.7.9 and 0.8.0 to VERSION union so it matches ExportData.version

Tests:
- Add replay-sensitive.test.ts covering false-positive avoidance
- Add parser test for shared fallback timestamp
2026-04-17 00:38:23 +01:00
Rohit Ghumare 4feff554eb Merge pull request #154 from rohitg00/fix/agent-sdk-quota-149
fix: warn on agent-sdk + AUTO_COMPRESS, accept GOOGLE_API_KEY as Gemini alias (#149)
2026-04-17 00:31:33 +01:00
Rohit Ghumare 11bef18927 feat: session replay tab + JSONL transcript import
Adds a Replay tab to the viewer that plays any stored session as a
scrubbable timeline (prompts, tool calls, tool results, responses)
with play/pause, speed control, and keyboard navigation.

Adds `agentmemory import-jsonl [path]` CLI subcommand and a matching
POST /agentmemory/replay/import-jsonl endpoint to backfill sessions
from Claude Code JSONL transcripts (default ~/.claude/projects).

All new logic routes through iii-sdk primitives: registerFunction for
mem::replay::load / mem::replay::sessions / mem::replay::import-jsonl,
and the existing HTTP trigger in api.ts for REST exposure.

Security: JSONL import rejects symlinks, paths containing sensitive
terms, and tolerates malformed lines without aborting the batch.
All imports are recorded in the audit log.
2026-04-17 00:26:14 +01:00
Rohit Ghumare 047ea8b636 Merge branch 'main' into fix/agent-sdk-quota-149 2026-04-16 23:54:14 +01:00
Rohit Ghumare 269fa65bde Merge pull request #153 from rohitg00/fix/symlink-compress-file-151
fix: reject symlinks in mem::compress-file (#151)
2026-04-16 23:36:59 +01:00
Rohit Ghumare 6810c7b38e fix: use || instead of ?? for GOOGLE_API_KEY fallback so empty strings fall through 2026-04-16 20:04:43 +01:00
Rohit Ghumare 05b6a0a370 fix: replace lstat-only symlink guard with O_NOFOLLOW at write time to close TOCTOU window
lstat alone has a TOCTOU race: a symlink swap between the check and the
writeFile call lets an attacker redirect the write. Replace the final write to
absolutePath with open(O_NOFOLLOW | O_WRONLY | O_CREAT | O_TRUNC) so the
kernel rejects the open atomically if the path is a symlink at open-time.
Keep lstat as a fast-fail before the LLM call. Handle ELOOP/EINVAL from open
and return the same "symlinks are not supported" error.

Tests: add open mock with ELOOP support, fix lstat mock to throw ENOENT for
unknown paths (matches runtime behavior), add TOCTOU test, add negative
assertions to the symlink test (no summarize call, no writes), add "file not
found" test for the ENOENT path.
2026-04-16 20:04:02 +01:00
Rohit Ghumare cad377d6fa fix: reject symlinks in mem::compress-file to prevent arbitrary file writes (#151)
lstat() check before any I/O now rejects symlinks, closing the bypass
where notes.md -> vault.txt passed the .md extension check but the
subsequent readFile/writeFile followed the symlink to the real target.

Adds a regression test that marks a path as a symlink in the mock and
verifies the function returns {success:false, error: "symlinks are not supported"}.
2026-04-16 19:24:24 +01:00
Rohit Ghumare 9eabbdc978 Merge pull request #152 from shaun0927/fix/compress-file-original-backup-collision
fix: preserve a distinct backup path for *.original.md inputs
2026-04-16 19:24:05 +01:00
Rohit Ghumare 12c15b582b fix: warn on agent-sdk + AUTO_COMPRESS, accept GOOGLE_API_KEY as Gemini alias (#149)
Two changes:
1. detectProvider() now accepts GOOGLE_API_KEY as an alias for GEMINI_API_KEY.
   Emits a stderr advisory to rename the variable.
2. When no provider key is found and AGENTMEMORY_AUTO_COMPRESS=true, emits a
   clear warning that agent-sdk will share Claude Code's API quota — the root
   cause of #149 where a wrong env var name caused silent fallback to agent-sdk
   during a heavy Opus session.
2026-04-16 19:20:54 +01:00
Rohit Ghumare 70ccc476d7 fix: reject symlinks in mem::compress-file to prevent arbitrary file writes (#151)
lstat() check before any I/O now rejects symlinks, closing the bypass
where notes.md -> vault.txt passed the .md extension check but the
subsequent readFile/writeFile followed the symlink to the real target.

Adds a regression test that marks a path as a symlink in the mock and
verifies the function returns {success:false, error: "symlinks are not supported"}.
2026-04-16 19:20:31 +01:00
JunghwanNA 471ccbc610 Preserve recoverable backups for already-suffixed compressed files
The new file-compression feature promises automatic backup creation,
but `*.original.md` inputs currently collapse the backup path onto the
source path and lose the original content. This keeps the common
`foo.md -> foo.original.md` behavior unchanged while assigning a
distinct backup name for already-suffixed inputs.

Constraint: Keep the fix narrow to backup-path generation and one regression test
Rejected: Introduce numbered backup discovery logic | larger behavior change than needed for the verified bug
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Preserve backup-path distinctness for any future suffix handling changes
Tested: npm test -- test/compress-file.test.ts; npm run build
Not-tested: Full npm test still hits an unrelated timeout in test/auto-compress.test.ts on this machine
2026-04-17 01:39:17 +09:00
Rohit Ghumare 1bdeaade8a chore: release v0.8.12
Bump package and plugin versions, update export/import compatibility, and add changelog notes for token-efficient recall and memory_compress_file.
v0.8.12
2026-04-16 10:39:40 +01:00
Rohit Ghumare 14da6c816c feat: add token-efficient recall and file compression tool (#150)
* feat: add token-efficient recall and file compression tool

Add memory_recall format and token budget support, plus a new memory_compress_file tool with API/MCP wiring, tests, and updated tool/endpoint docs.

* chore: remove temporary architecture assets

Delete temporary architecture and memory-cycle asset files added during implementation.
2026-04-16 10:36:17 +01:00
Rohit Ghumare aad6b7a70f Update GitHub Gist badge in README
Updated GitHub Gist badge to reflect new star and fork counts.
2026-04-15 21:53:09 +01:00
Rohit Ghumare 5a599c6a37 fix: split multi-word queries in standalone memory_smart_search (#148)
String.includes(query) required the full query to appear as a contiguous
substring, so "BEAM bi-level LLM" returned nothing even when each word
existed across title/content/concepts.

Split on whitespace and require every token to match (AND semantics).
Single-word queries are unaffected — a one-element array with .every
behaves identically to the old .includes.

Fixes #147
2026-04-15 21:51:46 +01:00
Rohit Ghumare 2c9911d2e1 chore: bump @agentmemory/mcp to 0.8.11, pin agentmemory dep to ~0.8.11 v0.8.11 2026-04-15 17:26:11 +01:00
Rohit Ghumare 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
2026-04-15 17:24:44 +01:00