Files
claude-mem/package.json
T
Alex Newman 5533412984 fix: sequoia-territory bug-fix bundle (chroma, env, build, MCP, worker) (#2394)
* fix(mcp): drop ${_R%/} parameter-expansion trim that trips Claude Code MCP validator

The POSIX substring trim ${_R%/} is misread by Claude Code's MCP-config
validator as a required env var named "_R%/", causing /doctor to flag
mcp-search as invalid on every install. POSIX collapses // in paths, so
the trim was cosmetic — drop it and the validator passes.

Fixes #2350, #2354, #2356.

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

* fix(env): block ANTHROPIC_BASE_URL leak + three-branch OAuth-skip predicate

Issue #2375: parent-shell ANTHROPIC_BASE_URL leaked through to subprocess
isolatedEnv, while ANTHROPIC_AUTH_TOKEN was blocked. The OAuth-skip
predicate fired on bare BASE_URL, but no auth credential reached the
subprocess -> "Not logged in". Add ANTHROPIC_BASE_URL to BLOCKED_ENV_VARS
so it can only enter isolatedEnv via ~/.claude-mem/.env.

Replace the OAuth-skip predicate with three branches to prevent a
second-order security regression: a user with a tokenless gateway
configured in .env (BASE_URL only, no token) would otherwise have their
Anthropic OAuth token fetched and sent to their gateway. Token leak to
third party. Three-branch predicate:

1. BASE_URL set -> return without OAuth (custom gateway, never leak token)
2. API_KEY or AUTH_TOKEN set -> return without OAuth (explicit credentials)
3. Otherwise -> OAuth lookup for api.anthropic.com

Adds tests/env-isolation.test.ts.

Fixes #2375.

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

* fix(worker): classify Claude SDK HTTP 400 as unrecoverable

ClaudeProvider previously had no explicit HTTP 400 handling — the
default branch classified all errors as `transient`, so a permanent
400 (e.g., model rejecting an `effort` parameter forwarded from a
leaked CLAUDE_CODE_EFFORT_LEVEL) would be retried indefinitely
(#1874+ retries observed in one session per #2357).

Mirror GeminiProvider/OpenRouterProvider's pattern: classify 400 as
`unrecoverable`, 401/403 as `auth_invalid`, 429 as `rate_limit`,
default to `transient`. When the 400 body matches the
"effort parameter" signature, emit a one-time SDK warn log pointing
at the env-leak fix in ~/.claude-mem/.env.

Adds tests/claude-provider-error-classifier.test.ts.

Fixes #2357.

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

* fix(chroma): pin onnxruntime>=1.20 + protobuf<7 to fix INVALID_PROTOBUF on macOS arm64

The shipped all-MiniLM-L6-v2 model has pytorch-2.0 IR. chroma-mcp 0.2.6
transitively depends on `chromadb>=1.0.16` which only requires
`onnxruntime>=1.14.1` — uv can therefore resolve to an onnxruntime old
enough to fail every embedding add with `[ONNXRuntimeError] : 7 :
INVALID_PROTOBUF` on macOS arm64 / Python 3.13. Semantic search silently
degraded to FTS-only and smart backfill broke (#2371).

Path B (override) was required because chroma-mcp 0.2.6 is the latest
PyPI release — no upstream bump exists.

Inject `--with onnxruntime>=1.20 --with protobuf<7` into the uvx spawn
args (both persistent and remote modes). The protobuf cap is essential:
forcing only `onnxruntime>=1.20` causes uv to re-resolve and land on
protobuf 7.x, which trips opentelemetry's `_pb2` stubs with `TypeError:
Descriptors cannot be created directly` because they were generated
with protoc <3.19. Capping below 7 lands on protobuf 6.x which
opentelemetry tolerates.

Verified end-to-end: ONNX model loads, embeddings produce a 384-dim
vector, PersistentClient init / add / query roundtrip succeeds:

    uvx --python 3.13 --with "onnxruntime>=1.20" --with "protobuf<7" \
        chroma-mcp==0.2.6 --help     # clean
    # programmatic test: onnxruntime 1.26.0, protobuf 6.33.6,
    # embedding ok 384, query ok ids=[['1']]

Fixes #2371.

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

* fix(chroma): enforce single chroma-mcp subprocess per worker (#2313)

Root cause: every reconnect path in ChromaMcpManager — connectInternal's
re-entry, the connect-timeout catch, callTool's transport-error retry, and
the transport.onclose handler — used to abandon `this.transport`/`this.client`
by calling at most `transport.close()` and nulling the handles. The MCP SDK's
StdioClientTransport.close() only signals the direct child (uvx); on Linux the
grandchildren (uv -> python -> chroma-mcp) re-parent to init and survive
because the SDK does not put the subprocess in its own process group. Each
reconnect therefore leaked a full chroma-mcp tree, accumulating 20+ instances
per session.

Fix: introduce a private disposeCurrentSubprocess() helper that always tree-
kills via the existing killProcessTree primitive before nulling the transport
reference, and route every "abandon current transport" path (reconnect,
connect-timeout, transport error, onclose, stop) through it. The existing
`connecting: Promise<void> | null` lock continues to serialize concurrent
ensureConnected() callers into a single spawn.

Adds tests/services/sync/chroma-mcp-manager-singleton.test.ts covering:
- 5 parallel ensureConnected() calls produce exactly one spawn
- a transport-error reconnect tree-kills the prior subprocess pid before
  spawning a replacement
- stop() disposes state including any pending connecting promise

Manual verification needed on Linux: after a long session with multiple
tool uses, `ps aux | grep chroma-mcp | wc -l` should return 1, not 20+.

Fixes #2313.

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

* fix(build): polyfill import.meta.url to __filename in CJS worker bundle

The worker bundles ESM dependencies (notably @anthropic-ai/claude-agent-sdk's
*.mjs files) into CJS output. Those modules call createRequire(import.meta.url)
at module-load time. esbuild's CJS output left this as createRequire(ute.url)
— where `ute` is its `import.meta` polyfill `{}` — so `ute.url` was undefined
and module-load crashed with:

  TypeError: The argument 'filename' must be a file URL object, file URL
  string, or absolute path string. Received undefined
  code: ERR_INVALID_ARG_VALUE

Every Stop hook and every worker subprocess invocation hit this. Fix is the
esbuild `define` option mapping `import.meta.url` to `__filename` (provided as
a real absolute path by the existing CJS prelude in the banner).

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

* chore: daily dep bump per CLAUDE.md maintenance policy

Root: @anthropic-ai/claude-agent-sdk, @clack/prompts, @types/node,
dompurify, postcss, react, react-dom, yaml, zod.
plugin/: tree-sitter-cli, zod.
openclaw/: @types/node.

All patch/minor bumps; no major version changes.

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

* build: regenerate plugin artifacts after env/chroma/mcp fixes

Built artifacts are committed so the marketplace-installable plugin
ships with the runtime bundles. Picks up:
- d7b145e9 .mcp.json shell-prelude trim drop
- a8cbd651 EnvManager BASE_URL block + 3-branch predicate
- 8cb73b8c ClaudeProvider HTTP 400 unrecoverable classifier
- ecd5b802 ChromaMcpManager onnxruntime/protobuf overrides
- c79324ea ChromaMcpManager singleton enforcement
- e8376f46 esbuild import.meta.url -> __filename polyfill
- a7541d71 daily dep bump

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

* build: regenerate plugin artifacts after main merge

Bundles now include both v13.0.0 server-beta runtime (server-beta-service.cjs
+ updated mcp-server.cjs / worker-service.cjs) and this branch's chroma /
env / build / Claude SDK fixes.

Verified: bun test tests/env-isolation.test.ts \\
  tests/claude-provider-error-classifier.test.ts \\
  tests/services/sync/chroma-mcp-manager-singleton.test.ts
→ 13/13 pass.

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

* fix(review): address CodeRabbit findings on PR #2394

1. scripts/build-hooks.js — `import.meta.url` now maps to a file:// URL
   (via pathToFileURL(__filename).href in the CJS banner) instead of the
   raw __filename path. Preserves URL semantics for any bundled ESM dep
   that does `new URL(rel, import.meta.url)`. createRequire still works.

2. src/shared/EnvManager.ts — added envFilePath() that resolves
   CLAUDE_MEM_ENV_FILE lazily (falling back to paths.envFile()), and
   switched internal load/save call sites to use it. ENV_FILE_PATH is
   kept as a deprecated snapshot for back-compat. Lets tests target a
   temp file without depending on module-load order.

3. tests/env-isolation.test.ts — redirects to a temp dir via
   CLAUDE_MEM_ENV_FILE in beforeAll, removes all mutation of the real
   ~/.claude-mem/.env, and wraps the OAuth-spy assertion in try/finally
   so the spy is always restored even if the test fails.

Verified:
  bun test tests/env-isolation.test.ts \
    tests/claude-provider-error-classifier.test.ts \
    tests/services/sync/chroma-mcp-manager-singleton.test.ts
  → 13/13 pass

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

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 18:05:48 -07:00

212 lines
7.4 KiB
JSON

{
"name": "claude-mem",
"version": "13.0.0",
"description": "Memory compression system for Claude Code - persist context across sessions",
"keywords": [
"claude",
"claude-code",
"claude-agent-sdk",
"mcp",
"plugin",
"memory",
"compression",
"knowledge-graph",
"transcript",
"typescript",
"nodejs"
],
"author": "Alex Newman",
"license": "Apache-2.0",
"repository": {
"type": "git",
"url": "https://github.com/thedotmack/claude-mem.git"
},
"homepage": "https://github.com/thedotmack/claude-mem#readme",
"bugs": {
"url": "https://github.com/thedotmack/claude-mem/issues"
},
"type": "module",
"bin": {
"claude-mem": "./dist/npx-cli/index.js"
},
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js"
},
"./sdk": {
"types": "./dist/sdk/index.d.ts",
"import": "./dist/sdk/index.js"
},
"./modes/*": "./plugin/modes/*"
},
"files": [
"dist",
".agents/plugins/marketplace.json",
".codex-plugin",
".mcp.json",
"plugin/.claude-plugin",
"plugin/.codex-plugin",
"plugin/.mcp.json",
"plugin/CLAUDE.md",
"plugin/package.json",
"plugin/hooks",
"plugin/modes",
"plugin/scripts/*.js",
"plugin/scripts/*.cjs",
"plugin/scripts/CLAUDE.md",
"plugin/skills",
"plugin/ui",
"openclaw"
],
"engines": {
"node": ">=20.0.0",
"bun": ">=1.0.0"
},
"scripts": {
"dev": "npm run build-and-sync",
"build": "node scripts/sync-plugin-manifests.js && node scripts/build-hooks.js",
"build-and-sync": "npm run build && npm run sync-marketplace && sleep 1 && (cd ~/.claude/plugins/marketplaces/thedotmack && npm run worker:restart)",
"sync-marketplace": "node scripts/sync-marketplace.cjs",
"sync-marketplace:force": "node scripts/sync-marketplace.cjs --force",
"build:binaries": "node scripts/build-worker-binary.js",
"build:cli-binary": "bun build --compile --minify ./src/services/worker-service.ts --outfile plugin/scripts/claude-mem",
"worker:logs": "tail -n 50 ~/.claude-mem/logs/worker-$(date +%Y-%m-%d).log",
"worker:tail": "tail -f 50 ~/.claude-mem/logs/worker-$(date +%Y-%m-%d).log",
"changelog:generate": "node scripts/generate-changelog.js",
"discord:notify": "node scripts/discord-release-notify.js",
"worker:start": "bun plugin/scripts/worker-service.cjs start",
"worker:stop": "bun plugin/scripts/worker-service.cjs stop",
"worker:restart": "bun plugin/scripts/worker-service.cjs restart",
"worker:status": "bun plugin/scripts/worker-service.cjs status",
"queue": "bun scripts/check-pending-queue.ts",
"queue:process": "bun scripts/check-pending-queue.ts --process",
"queue:clear:pending": "bun scripts/clear-pending-queue.ts --all --force",
"pr:status": "bun scripts/pr-babysit-status.ts",
"claude-md:regenerate": "bun scripts/regenerate-claude-md.ts",
"claude-md:dry-run": "bun scripts/regenerate-claude-md.ts --dry-run",
"strip-comments": "bun scripts/strip-comments.ts",
"strip-comments:check": "bun scripts/strip-comments.ts --check",
"strip-comments:dry-run": "bun scripts/strip-comments.ts --dry-run",
"translate-readme": "bun scripts/translate-readme/cli.ts -v -o docs/i18n README.md",
"translate:tier1": "npm run translate-readme -- zh zh-tw ja pt-br ko es de fr",
"translate:tier2": "npm run translate-readme -- he ar ru pl cs nl tr uk",
"translate:tier3": "npm run translate-readme -- vi id th hi bn ro sv",
"translate:tier4": "npm run translate-readme -- it el hu fi da no",
"translate:all": "npm run translate:tier1 & npm run translate:tier2 & npm run translate:tier3 & npm run translate:tier4 & wait",
"bug-report": "npx tsx scripts/bug-report/cli.ts",
"cursor:install": "bun plugin/scripts/worker-service.cjs cursor install",
"cursor:uninstall": "bun plugin/scripts/worker-service.cjs cursor uninstall",
"cursor:status": "bun plugin/scripts/worker-service.cjs cursor status",
"cursor:setup": "bun plugin/scripts/worker-service.cjs cursor setup",
"typecheck": "tsc --noEmit && tsc --noEmit -p src/ui/viewer/tsconfig.json",
"typecheck:root": "tsc --noEmit",
"typecheck:viewer": "tsc --noEmit -p src/ui/viewer/tsconfig.json",
"test": "bun test",
"test:sqlite": "bun test tests/sqlite/",
"test:agents": "bun test tests/worker/agents/",
"test:search": "bun test tests/worker/search/",
"test:context": "bun test tests/context/",
"test:infra": "bun test tests/infrastructure/",
"test:server": "bun test tests/server/",
"e2e:server-beta:docker": "bash scripts/e2e-server-beta-docker.sh",
"prepublishOnly": "npm run build",
"release": "np",
"release:patch": "np patch --no-cleanup",
"release:minor": "np minor --no-cleanup",
"release:major": "np major --no-cleanup"
},
"np": {
"yarn": false,
"contents": ".",
"testScript": "test",
"2fa": false
},
"dependencies": {
"@anthropic-ai/claude-agent-sdk": "^0.2.138",
"@better-auth/api-key": "^1.6.9",
"@clack/prompts": "^1.3.0",
"@modelcontextprotocol/sdk": "^1.29.0",
"ansi-to-html": "^0.7.2",
"better-auth": "^1.6.9",
"bullmq": "^5.76.6",
"cors": "^2.8.6",
"dompurify": "^3.4.2",
"express": "^5.2.1",
"glob": "^13.0.6",
"handlebars": "^4.7.9",
"ioredis": "^5.10.1",
"pg": "^8.20.0",
"picocolors": "^1.1.1",
"react": "^19.2.6",
"react-dom": "^19.2.6",
"shell-quote": "^1.8.3",
"yaml": "^2.8.4",
"zod": "^4.4.3",
"zod-to-json-schema": "^3.25.2"
},
"devDependencies": {
"@derekstride/tree-sitter-sql": "^0.3.11",
"@tree-sitter-grammars/tree-sitter-lua": "^0.4.1",
"@tree-sitter-grammars/tree-sitter-markdown": "^0.3.2",
"@tree-sitter-grammars/tree-sitter-toml": "^0.7.0",
"@tree-sitter-grammars/tree-sitter-yaml": "^0.7.1",
"@tree-sitter-grammars/tree-sitter-zig": "^1.1.2",
"@types/bun": "^1.3.13",
"@types/cors": "^2.8.19",
"@types/dompurify": "^3.2.0",
"@types/express": "^5.0.6",
"@types/node": "^25.6.2",
"@types/pg": "^8.20.0",
"@types/react": "^19.2.14",
"@types/react-dom": "^19.2.3",
"esbuild": "^0.28.0",
"jimp": "^1.6.1",
"np": "^11.2.0",
"parse5": "^8.0.1",
"postcss": "^8.5.14",
"remark-mdx": "^3.1.1",
"remark-parse": "^11.0.0",
"tree-sitter-bash": "^0.25.1",
"tree-sitter-c": "^0.24.1",
"tree-sitter-cli": "^0.26.8",
"tree-sitter-cpp": "^0.23.4",
"tree-sitter-css": "^0.25.0",
"tree-sitter-elixir": "^0.3.5",
"tree-sitter-go": "^0.25.0",
"tree-sitter-haskell": "^0.23.1",
"tree-sitter-java": "^0.23.5",
"tree-sitter-javascript": "^0.25.0",
"tree-sitter-kotlin": "^0.3.8",
"tree-sitter-php": "^0.24.2",
"tree-sitter-python": "^0.25.0",
"tree-sitter-ruby": "^0.23.1",
"tree-sitter-rust": "^0.24.0",
"tree-sitter-scala": "^0.24.0",
"tree-sitter-scss": "^1.0.0",
"tree-sitter-swift": "^0.7.1",
"tree-sitter-typescript": "^0.23.2",
"ts-prune": "^0.10.3",
"tsx": "^4.21.0",
"typescript": "^6.0.3",
"unified": "^11.0.5",
"unist-util-visit": "^5.1.0"
},
"optionalDependencies": {
"tree-kill": "^1.2.2"
},
"trustedDependencies": [
"esbuild",
"tree-sitter-c",
"tree-sitter-cli",
"tree-sitter-cpp",
"tree-sitter-go",
"tree-sitter-java",
"tree-sitter-javascript",
"tree-sitter-python",
"tree-sitter-ruby",
"tree-sitter-rust",
"tree-sitter-typescript"
]
}