Commit Graph

1710 Commits

Author SHA1 Message Date
Ben Younes f97c50bfb9 fix: session lifecycle guards to prevent runaway API spend (#1590) (#1693)
* fix: add session lifecycle guards to prevent runaway API spend (#1590)

Three root causes allowed 30+ subprocess accumulation over 36 hours:
1. SIGTERM-killed processes (code 143) triggered crash recovery and
   immediately respawned — now detected and treated as intentional
   termination (aborts controller so wasAborted=true in .finally).
2. No wall-clock limit: sessions ran for 13+ hours continuously
   spending tokens — now refuses new generators after 4 hours and
   drains the pending queue to prevent further spawning.
3. Duplicate --resume processes for the same session UUID — now
   killed and unregistered before a new spawn is registered.

Generated by Claude Code
Vibe coded by ousamabenyounes

Co-Authored-By: Claude <noreply@anthropic.com>

* fix: use normalized errorMsg in logger.error payload and annotate SIGTERM override

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: use persisted createdAt for wall-clock guard and bind abortController locally to prevent stale abort

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* chore: re-trigger CodeRabbit review after rate limit reset

* fix: defer process unregistration until exit and align boundary test with strict > (#1693)

- ProcessRegistry: don't unregister PID immediately after SIGTERM — let the
  existing 'exit' handler clean up when the process actually exits, preventing
  tracking loss for still-live processes.
- Test: align wall-clock boundary test with production's strict `>` operator
  (exactly 4h is NOT terminated, only >4h is).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-04-15 00:58:23 -07:00
Ben Younes 983be42998 fix: resolve Gemini CLI 0.37.0 session capture failures (#1664) (#1692)
Three root causes prevented Gemini sessions from persisting prompts,
observations, and summaries:

1. BeforeAgent was mapped to user-message (display-only) instead of
   session-init (which initialises the session and starts the SDK agent).

2. The transcript parser expected Claude Code JSONL (type: "assistant")
   but Gemini CLI 0.37.0 writes a JSON document with a messages array
   where assistant entries carry type: "gemini". extractLastMessage now
   detects the format and routes to the correct parser, preserving
   full backward compatibility with Claude Code JSONL transcripts.

3. The summarize handler omitted platformSource from the
   /api/sessions/summarize request body, causing sessions to be recorded
   without the gemini-cli source tag.

Co-authored-by: Claude <noreply@anthropic.com>
2026-04-15 00:58:20 -07:00
UCHIDA Masayuki 544e9d39f5 fix: replace hardcoded nvm/homebrew PATH with universal login shell resolution (#1833)
* fix: replace hardcoded nvm/homebrew PATH with universal login shell resolution

Hook commands previously hardcoded PATH entries for nvm and homebrew,
causing `node: command not found` for users with other Node version
managers (mise, asdf, volta, fnm, Nix, etc.).

Replace with `$($SHELL -lc 'echo $PATH')` which inherits the user's
login shell PATH regardless of how Node was installed. Also adds the
missing PATH export to the PreToolUse hook (#1702).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: add cache-path fallback to PreToolUse hook

Aligns PreToolUse _R resolution with all other hooks by adding the
cache directory lookup before falling back to the marketplace path.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-15 00:58:17 -07:00
Ethan 16a0737dfc fix: use parent project name for worktree observation writes (#1820)
* fix: use parent project name for worktree observation writes (#1819)

Observations and sessions from git worktrees were stored under
basename(cwd) instead of the parent repo name because write paths
called getProjectName() (not worktree-aware) instead of
getProjectContext() (worktree-aware). This is the same bug as
#1081, #1317, and #1500 — it regressed because the two functions
coexist and new code reached for the simpler one.

Fix: getProjectContext() now returns parentProjectName as primary
when in a worktree, and all four write-path call sites now use
getProjectContext().primary instead of getProjectName().

Includes regression test that creates a real worktree directory
structure and asserts primary === parentProjectName.

* fix: address review nitpicks — allProjects fallback, JSDoc, write-path test

- ContextBuilder: default projects to context.allProjects for legacy
  worktree-labeled record compatibility
- ProjectContext: clarify JSDoc that primary is canonical (parent repo
  in worktrees)
- Tests: add write-path regression test mirroring session-init/SessionRoutes
  pattern; refactor worktree fixture into beforeAll/afterAll

* refactor(project-name): rename local to cwdProjectName and dedupe allProjects

Addresses final CodeRabbit nitpick: disambiguates the local variable
from the returned `primary` field, and dedupes allProjects via Set
in case parent and cwd resolve to the same name.

---------

Co-authored-by: Ethan Hurst <ethan.hurst@outlook.com.au>
2026-04-15 00:58:14 -07:00
biswanath-cmd 3d92684e04 fix: filter empty string args before Bun spawn() to prevent CLI parsing errors (#1781)
Bun's child_process.spawn() silently drops empty string arguments from
argv, unlike Node which preserves them. When the Agent SDK defaults
settingSources to [] (empty array), [].join(",") produces "" which gets
pushed as ["--setting-sources", ""]. Bun drops the "", causing
--permission-mode to be consumed as the value for --setting-sources:

  Error processing --setting-sources: Invalid setting source: --permission-mode

This caused 100% observation failure (exit code 1 on every SDK subprocess
spawn), resulting in 0 observations stored across all sessions.

The fix filters empty string args before passing to spawn(), making the
behavior consistent between Node and Bun runtimes.

Fixes #1779
Related: #1660

Co-authored-by: bswnth48 <69203760+bswnth48@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 00:58:11 -07:00
enma998 471e1f62f9 Fix npx search and default Codex context to workspace-local AGENTS (#1780)
* Fix npx search query parameter mismatch

* Use workspace-local Codex AGENTS context by default

---------

Co-authored-by: bnb <bnb>
2026-04-15 00:58:08 -07:00
Aviral Arora f44605658d docs: add CLAUDE_MEM_MODE documentation for language and modes (fix #… (#1777)
* docs: add CLAUDE_MEM_MODE documentation for language and modes (fix #1767)

* docs: fix markdown formatting for CLAUDE_MEM_MODE section

* docs: fix markdown code block formatting properly

* docs: fix markdown issues in modes section

* docs: fix markdown spacing and table note formatting

* Update README.md

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* docs: fix markdown

* docs: fix markdown issues in modes

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-04-15 00:58:05 -07:00
suyua9 eeb6841033 fix: coerce corpus route filters (#1776)
* fix: coerce corpus route filters

* test: cover unsupported corpus type filters
2026-04-15 00:58:01 -07:00
Tran Quang 2a2008bac2 fix(file-context): preserve targeted reads + invalidate on mtime (#1719) (#1729)
* fix(file-context): preserve targeted reads + invalidate on mtime (#1719)

The PreToolUse:Read hook unconditionally rewrote tool input to
{file_path, limit:1}, which interacted with two failure modes:

1. Subagent edits a file → parent's next Read still gets truncated
   because the observation snapshot predates the change.
2. Claude requests a different section with offset/limit → the hook
   strips them, so the Claude Code harness's read-dedup cache returns
   "File unchanged" against the prior 1-line read. The file becomes
   unreadable for the rest of the conversation, even though the hook's
   own recovery hint says "Read again with offset/limit for the
   section you need."

Two complementary fixes:

- **mtime invalidation**: stat the file (we already stat for the size
  gate) and compare mtimeMs to the newest observation's created_at_epoch.
  If the file is newer, pass the read through unchanged so fresh content
  reaches Claude.

- **Targeted-read pass-through**: when toolInput already specifies
  offset and/or limit, preserve them in updatedInput instead of
  collapsing to {limit:1}. The harness's dedup cache then sees a
  distinct input and lets the read proceed.

The unconstrained-read path (no offset, no limit) is unchanged: still
truncated to 1 line plus the observation timeline, so token economics
are preserved for the common case.

Tests cover all three branches: existing truncation, targeted-read
pass-through (offset+limit, limit-only), and mtime-driven bypass.

Fixes #1719

* refactor(file-context): address review findings on #1719 fix

- Add offset-only test case for full targeted-read branch coverage
- Use >= for mtime comparison to handle same-millisecond edge case
- Add Number.isFinite() + bounds guards on offset/limit pass-through
- Trim over-verbose comments to concise single-line summaries
- Remove redundant `as number` casts after typeof narrowing
- Add comment explaining fileMtimeMs=0 sentinel invariant
2026-04-15 00:57:57 -07:00
Suryansh Rohil d64c252f4d Update: Updated readme for opencode installation (#1765) 2026-04-15 00:57:54 -07:00
Jochen Meyer 59ce0fc553 fix: exclude primary key index from unique constraint check in migration 7 (#1771)
* fix: exclude primary key index from unique constraint check in migration 7

PRAGMA index_list returns all indexes including those backing PRIMARY KEY
columns (origin='pk'), which always have unique=1. The check was therefore
always true, causing migration 7 to run the full DROP/CREATE/RENAME table
sequence on every worker startup instead of short-circuiting once the
UNIQUE constraint had already been removed.

Fix: filter to non-PK indexes by requiring idx.origin !== 'pk'. The
origin field is already present on the existing IndexInfo interface.

Fixes #1749

* fix: apply pk-origin guard to all three migration code paths

CodeRabbit correctly identified that the origin !== 'pk' fix was only
applied to MigrationRunner.ts but not to the two other active code paths
that run the same removeSessionSummariesUniqueConstraint logic:

- SessionStore.ts:220 — used by DatabaseManager and worker-service
- plugin/scripts/context-generator.cjs — bundled artifact (minified)

All three paths now consistently exclude primary-key indexes when
detecting unique constraints on session_summaries.
2026-04-15 00:57:51 -07:00
Jochen Meyer 31ee1024c5 fix: restrict ~/.claude-mem/.env permissions to owner-only (0600) (#1770)
* fix: restrict .env file permissions to owner-only (0600)

API keys stored in ~/.claude-mem/.env were created without explicit
permissions, defaulting to umask-dependent mode. On systems with a
permissive umask (e.g. 0022), the file would be world-readable.

- Set directory permissions to 0700 on creation
- Set file permissions to 0600 via writeFileSync mode option
- Call chmodSync after write to fix permissions on pre-existing files

Signed-off-by: Jochen Meyer

* fix: also restrict pre-existing directory permissions to 0700

The initial fix only set directory mode on creation. Pre-existing
~/.claude-mem/ directories from earlier installs remained world-readable.
Add chmodSync for the directory alongside the existing file chmod,
and document the Windows limitation (ACLs, not POSIX permissions).

---------

Signed-off-by: Jochen Meyer
2026-04-15 00:57:48 -07:00
Alex Newman 7d5d4c5036 docs: update CHANGELOG.md for v12.1.1
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 19:16:36 -07:00
Alex Newman 06b997e3d0 chore: bump version to 12.1.1
Publish to npm / publish (push) Has been cancelled
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
v12.1.1
2026-04-14 19:14:03 -07:00
Alex Newman a390a537c9 fix: broadcast uses summaryForStore to support salvaged summaries (#1718)
syncAndBroadcastSummary was using the raw ParsedSummary (null when salvaged)
instead of summaryForStore for the SSE broadcast, causing a crash when the
LLM returns <observation> without <summary> tags. Also removes misplaced
tree-sitter docs from mem-search/SKILL.md (belongs in smart-explore).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 19:11:48 -07:00
Alex Newman 2357835942 Merge pull request #1686 from ousamabenyounes/fix/issue-1633
fix: expose summaryStored in session status to detect silent summary loss (#1633)
2026-04-14 18:41:58 -07:00
Alex Newman 77a22d30b2 Merge pull request #1555 from ousamabenyounes/fix/issue-1384-mcp-inputschema
fix: declare inputSchema properties for search and timeline MCP tools (#1384 #1413)
2026-04-14 18:41:54 -07:00
Alex Newman 40a25e0225 Merge pull request #1676 from ousamabenyounes/fix/issue-1625
fix: filter ghost observations with no content fields (#1625)
2026-04-14 18:41:51 -07:00
Alex Newman 4c2ab98d90 Merge pull request #1679 from ousamabenyounes/fix/issue-1297
fix: set cwd to homedir when spawning chroma-mcp to prevent pydantic .env.local crash (#1297)
2026-04-14 18:41:48 -07:00
Alex Newman 7bcfd73985 Merge pull request #1677 from ousamabenyounes/fix/issue-1503
fix: avoid DEP0190 deprecation on Windows by using single-string spawnSync for where bun (#1503)
2026-04-14 18:41:34 -07:00
Alex Newman 7dd321f869 Merge pull request #1678 from ousamabenyounes/fix/issue-1342
fix: add .gitattributes to enforce LF endings on plugin scripts (#1342)
2026-04-14 18:41:31 -07:00
Alex Newman 153ddb814b Merge pull request #1670 from ousamabenyounes/fix/issue-1651
docs: add Language Support section to smart-explore/SKILL.md (#1651)
2026-04-14 18:41:28 -07:00
Alex Newman 216d17879d Merge pull request #1680 from ousamabenyounes/fix/issue-1447
fix: suppress false ERROR when duplicate daemon loses port bind race (#1447)
2026-04-14 18:41:25 -07:00
Alex Newman fa73dd483c Merge pull request #1666 from ousamabenyounes/fix/issue-1299
fix: remove leaky mock.module() for project-name that polluted parallel workers (#1299)
2026-04-14 18:41:22 -07:00
Alex Newman 9dd0ae10a3 Merge pull request #1658 from octo-patch/fix/issue-1648-mcp-server-use-bun-command
fix: use bun to run mcp-server.cjs instead of node shebang
2026-04-14 18:41:17 -07:00
Alex Newman 9a91a1be2b Merge pull request #1701 from ck0park/fix/list-corpora-mcp-result-shape
fix: list_corpora MCP tool — wrap response in CallToolResult shape (fixes #1700)
2026-04-14 18:41:13 -07:00
Alex Newman a5b2c26592 Merge pull request #1718 from aaronwong1989/fix/1312-summary-salvage-from-observations
fix(ResponseProcessor): salvage synthetic summary when AI returns <observation> instead of <summary> (Issue #1312)
2026-04-14 18:41:10 -07:00
Alex Newman fc9331fc39 Merge pull request #1724 from kbroughton/fix/upgrade-glob-v11-to-v13
fix(deps): upgrade glob ^11.0.3 → ^13.0.0 (fixes #1717)
2026-04-14 18:41:07 -07:00
Alex Newman ff17609a81 Merge pull request #1725 from joao-oliveira-softtor/fix/sessionstart-hook-worker-race-soft-fail
fix(hooks): soft-fail SessionStart health check on cold start
2026-04-14 18:41:04 -07:00
joaovictorolvr fe8737420d fix(hooks): soft-fail SessionStart health check on cold start
The three SessionStart hooks poll http://localhost:37777/health with an
8-second retry budget and then exit 1 silently (via `curl -sf || exit 1`)
when the worker has not stabilized in time. Claude Code surfaces this as
two `SessionStart:startup hook error - Failed with non-blocking status
code: No stderr output` messages on every first session of the day.

This happens because of a race between the MCP server auto-starting the
worker and the hook's own `worker-service.cjs start` path, which on Linux
respects a live PID file written by an earlier session and waits for the
existing worker to become healthy. 8s is not always enough.

Mitigate in the hook layer without touching worker-service.cjs:

- bump the inner retry loop from 8 to 20 attempts (up to ~20s)
- replace `|| exit 1` with `|| true` so the hook emits its continue JSON
  regardless (Claude Code no longer logs a phantom error)
- guard the context-injection hook with a health check - only run
  `worker-service.cjs hook claude-code context` if the worker is actually
  responding, otherwise skip silently

Trade-off: on cold starts where the worker takes longer than ~20s to
come up, the recent-context preamble is skipped for that first session
instead of surfacing an error. Subsequent sessions in the same day work
normally because the worker is already healthy.

Refs #1447
2026-04-11 16:20:03 -03:00
kbroughton 8275b3da3b fix(deps): upgrade glob from ^11.0.3 to ^13.0.0 (fixes #1717)
glob@11.x is deprecated by its maintainer and flagged as containing
widely-publicised security vulnerabilities (including ReDoS risks).
The latest stable version is glob@13.0.6.

Compatibility verified: the codebase uses only `globSync` with
`{ nodir, absolute }` options in two files:
- src/services/transcripts/watcher.ts
- scripts/analyze-transformations-smart.js

The `globSync` function signature and these options are identical
in glob@13. No call-site changes are required.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 11:00:37 -05:00
Sisyphus 🏔️ b7c23ca232 fix(ResponseProcessor): salvage synthetic summary when AI returns <observation> instead of <summary>
Fixes Issue #1312: AI sometimes returns <observation> XML tags instead of
<summary> tags during the summarize phase, despite clear instructions in
buildSummaryPrompt() requiring <summary> ONLY output.

When this occurs, parseSummary() returns null and the entire session summary
is lost. This fix detects the condition (summary missing + observations
present) and synthesizes a summary from the observation data, ensuring
session summaries are not completely lost.

The salvage mapping:
- request: observation title
- investigated: observation narrative or facts
- learned: observation facts joined
- completed: title if type is feature/bugfix
- notes: indicates this is a synthetic salvage summary

Observations are stored normally regardless of this fallback.

Co-authored-by: Sisyphus <sisyphus@openclaw>
2026-04-11 20:29:35 +08:00
Ousama Ben Younes edc8535ac1 fix: skip queueLength===0 completion branch when session returns 404 2026-04-11 08:16:35 +00:00
ck0park ad127bec40 fix: wrap list_corpora response in MCP CallToolResult shape (fixes #1700)
GET /api/corpus returned a bare array, which the MCP server wrapper
(callWorkerAPI) forwards directly. MCP's tools/call validation rejects
non-object results with "expected object, received array", so the
list_corpora MCP tool was completely unusable.

Every other corpus endpoint is a POST that already returns the
{content:[...]} shape, so this is a targeted one-file fix.
2026-04-11 09:57:01 +09:00
Ousama Ben Younes 2f19eab9c2 fix: expose summaryStored in session status to detect silent summary loss (#1633)
Stop hook polled queueLength===0 as a proxy for summary success, but the queue
empties regardless of whether the LLM produced valid <summary> tags. Added
lastSummaryStored tracking on ActiveSession, surfaced via the /api/sessions/status
endpoint, and emit a logger.warn in the Stop hook when summaryStored===false.

Generated by Claude Code
Vibe coded by ousamabenyounes

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-10 15:06:18 +00:00
Ousama Ben Younes e7bf2ac65a docs: add custom grammar and markdown special support sections to smart-explore/SKILL.md
- Add Custom Grammars (.claude-mem.json) section explaining how to register
  additional tree-sitter parsers for unsupported file extensions
- Add Markdown Special Support section documenting heading-based outline,
  code-fence search, section unfold, and frontmatter extraction behaviors
- Expand bundled language test to cover all 10 documented languages plus
  the plain-text fallback sentence to prevent partial doc regressions

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-10 10:52:31 +00:00
Ousama Ben Younes 5ac54239d8 fix: add context-generator.cjs to SHEBANG_SCRIPTS and assert file existence
- Add missing context-generator.cjs to the SHEBANG_SCRIPTS list so CRLF
  regressions in that script are caught by the test suite
- Replace silent early-returns with expect(existsSync(filePath)).toBe(true)
  so the suite fails loudly when expected build artifacts are absent

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-10 10:51:34 +00:00
Ousama Ben Younes 08cf2ba3bd fix: suppress false ERROR when duplicate daemon loses port bind race (#1447)
When the MCP server and SessionStart hook both spawn a worker daemon
concurrently, one loses the bind race (EADDRINUSE / Bun's port-in-use
error). The loser now checks if the winner is healthy; if so, it logs
INFO and exits cleanly instead of logging a misleading ERROR on every
first session start.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 10:01:08 +00:00
Ousama Ben Younes c7c4fd54d6 fix: set cwd to homedir when spawning chroma-mcp to prevent pydantic .env.local crash (#1297)
chroma-mcp uses pydantic-settings which auto-reads .env/.env.local from
the CWD. When the project directory contains non-chroma variables (e.g.
CELERY_TASK_ALWAYS_EAGER), pydantic rejects them with "Extra inputs are
not permitted", crashing the subprocess and triggering a permanent
backoff loop. Passing cwd: os.homedir() to StdioClientTransport ensures
pydantic never reads project env files.

Generated by Claude Code
Vibe coded by ousamabenyounes

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-10 09:55:02 +00:00
Ousama Ben Younes f61eb2d162 fix: add .gitattributes to enforce LF endings on plugin scripts (#1342)
Without .gitattributes, building on Windows produces plugin scripts with
CRLF line endings. The CRLF on the shebang line causes
"env: node\r: No such file or directory" on macOS/Linux, breaking the
MCP server and all hook scripts. Add text=auto eol=lf as the global
default plus explicit eol=lf rules for plugin/scripts/*.cjs and *.js.

Generated by Claude Code
Vibe coded by ousamabenyounes

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-10 09:51:22 +00:00
Ousama Ben Younes e9a234308a fix: avoid DEP0190 deprecation on Windows by using single-string spawnSync for where bun (#1503)
Node 22+ emits DEP0190 when spawnSync is called with a separate args
array and shell:true, because the args are only concatenated (not
escaped). Split the findBun() PATH check into platform-specific calls:
Windows uses spawnSync('where bun', { shell: true }) as a single string,
Unix uses spawnSync('which', ['bun']) with no shell option.

Generated by Claude Code
Vibe coded by ousamabenyounes

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-10 09:49:23 +00:00
Ousama Ben Younes e398212983 fix: filter ghost observations with no content fields (#1625)
When the LLM is overwhelmed by large context it can emit bare
<observation/> blocks (or ones containing only <type>). These are
stored as rows where title, narrative, facts and concepts are all
null/empty, appearing as meaningless "Untitled" entries in the context
window. Add a guard in parseObservations() that skips any observation
where every content field is null/empty before pushing it to the
result array.

Generated by Claude Code
Vibe coded by ousamabenyounes

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-10 09:40:40 +00:00
Ousama Ben Younes 36a03f75b2 docs: add Language Support section to smart-explore/SKILL.md (#1651)
tree-sitter language docs belonged in smart-explore but were absent;
this adds the Bundled Languages table (10 languages) with correct placement.

Generated by Claude Code
Vibe coded by ousamabenyounes

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-09 23:24:14 +00:00
Ousama Ben Younes 5676cab83f fix: remove leaky mock.module() for project-name that polluted parallel workers (#1299)
Top-level mock.module() in context-reinjection-guard.test.ts permanently stubbed
getProjectName() to 'test-project' for the entire Bun worker process, causing
tests in other files to receive the wrong value. Removed the unnecessary mock
(session-init tests don't assert on project name), added bunfig.toml smol=true
for worker isolation, and added a regression test.

Generated by Claude Code
Vibe coded by ousamabenyounes

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-09 22:55:54 +00:00
octo-patch 126129fbac fix: use bun to run mcp-server.cjs instead of node shebang (fixes #1648)
The mcp-server.cjs script requires bun:sqlite, a Bun-specific built-in
that is unavailable in Node.js. When Claude Code spawns the script using
the shebang (#!/usr/bin/env node), the import fails with:
  Error: Cannot find module 'bun:sqlite'

Fix: explicitly invoke bun as the command and pass the script as an arg,
so the correct runtime is used regardless of the shebang line.
2026-04-09 09:29:23 +08:00
Alex Newman cde4faae2f docs: update CHANGELOG.md for v12.1.0
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 17:37:57 -07:00
Alex Newman b701bf29e6 chore: bump version to 12.1.0
Publish to npm / publish (push) Has been cancelled
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
v12.1.0
2026-04-08 17:31:19 -07:00
Alex Newman c648d5d8d2 feat: Knowledge Agents — queryable corpora from claude-mem (#1653)
* feat: add knowledge agent types, store, builder, and renderer

Phase 1 of Knowledge Agents feature. Introduces corpus compilation
pipeline that filters observations from the database into portable
corpus files stored at ~/.claude-mem/corpora/.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add corpus CRUD HTTP endpoints and wire into worker service

Phase 2 of Knowledge Agents. Adds CorpusRoutes with 5 endpoints
(build, list, get, delete, rebuild) and registers them during
worker background initialization alongside SearchRoutes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add KnowledgeAgent with V1 SDK prime/query/reprime

Phase 3 of Knowledge Agents. Uses Agent SDK V1 query() with
resume and disallowedTools for Q&A-only knowledge sessions.
Auto-reprimes on session expiry. Adds prime, query, and reprime
HTTP endpoints to CorpusRoutes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add MCP tools and skill for knowledge agents

Phase 4 of Knowledge Agents. Adds build_corpus, list_corpora,
prime_corpus, and query_corpus MCP tools delegating to worker
HTTP endpoints. Includes /knowledge-agent skill with workflow docs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: handle SDK process exit in KnowledgeAgent, add e2e test

The Agent SDK may throw after yielding all messages when the
Claude process exits with a non-zero code. Now tolerates this
if session_id/answer were already captured. Adds comprehensive
e2e test script (31 assertions) orchestrated via tmux-cli.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: use settings model ID instead of hardcoded model in KnowledgeAgent

Reads CLAUDE_MEM_MODEL from user settings via getModelId(), matching
the existing SDKAgent pattern. No more hardcoded model assumptions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: improve knowledge agents developer experience

Add public documentation page, rebuild/reprime MCP tools, and actionable
error messages. DX review scored knowledge agents 4/10 — core engineering
works (31/31 e2e) but the feature was invisible. This addresses
discoverability (docs, cross-links), API completeness (missing MCP tools),
and error quality (fix/example fields in error responses).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* docs: add quick start guide to knowledge agents page

Covers the three main use cases upfront: creating an agent, asking a
single question, and starting a fresh conversation with reprime. Includes
keeping-it-current section for rebuild + reprime workflow.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: address code review issues — path traversal, session safety, prompt injection

- Block path traversal in CorpusStore with alphanumeric name validation and resolved path check
- Harden system prompt against instruction injection from untrusted corpus content
- Validate question field as non-empty string in query endpoint
- Only persist session_id after successful prime (not null on failure)
- Persist refreshed session_id after query execution
- Only auto-reprime on session resume errors, not all query failures
- Add fenced code block language tags to SKILL.md

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: address remaining code review issues — e2e robustness, MCP validation, docs

- Harden e2e curl wrappers with connect-timeout, fallback to HTTP 000 on transport failure
- Use curl_post wrapper consistently for all long-running POST calls
- Add runtime name validation to all corpus MCP tool handlers
- Fix docs: soften hallucination guarantee to probabilistic claim
- Fix architecture diagram: add missing rebuild_corpus and reprime_corpus tools

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: enforce string[] type in safeParseJsonArray for corpus data integrity

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: add blank line before fenced code blocks in SKILL.md maintenance section

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 17:30:20 -07:00
WuTao 07be61cf91 feat: support ANTHROPIC_BASE_URL in EnvManager (#1627)
* feat: add custom OpenRouter base URL support

Allow users to configure a custom base URL for OpenRouter API calls
through settings UI and environment management.

Generated with AI

Co-Authored-By: AI Partner

* refactor: remove OpenRouter base URL customization, keep Claude URL changes

Only retain ANTHROPIC_BASE_URL and ANTHROPIC_AUTH_TOKEN support in
EnvManager for custom Claude API endpoint configuration.

Generated with AI

Co-Authored-By: AI Partner

* chore: revert build artifacts to match main

Generated with AI

Co-Authored-By: AI Partner

* fix: remove ANTHROPIC_AUTH_TOKEN, add ANTHROPIC_BASE_URL persistence

- Remove unnecessary ANTHROPIC_AUTH_TOKEN (inherited from parent process)
- Add ANTHROPIC_BASE_URL to saveClaudeMemEnv() to fix config persistence
- Keep only ANTHROPIC_BASE_URL support for custom API endpoint

Generated with AI

Co-Authored-By: AI Partner
2026-04-08 16:17:06 -07:00
Octopus f7fd2221c8 fix: rebuild FTS5 index after bulk observation import (fixes #1631) (#1632)
Imported observations were invisible to the MCP search tool because the
FTS5 content table was not reliably updated during bulk import. The import
handler now calls rebuildObservationsFTSIndex() after inserting new
observations, ensuring the full-text search index is consistent.

A new SessionStore.rebuildObservationsFTSIndex() method encapsulates the
FTS5 rebuild command and is a no-op when the observations_fts table does
not exist (e.g. FTS5 unavailable on Windows).
2026-04-08 16:16:55 -07:00