Commit Graph

1759 Commits

Author SHA1 Message Date
Alex Newman ae6915b88e fix: address PR review — shebang, double-escaping, data loss, uninstall scope
- Add shebang banner to NPX CLI esbuild config so npx claude-mem works
- Remove manual backslash pre-escaping in WindsurfHooksInstaller (JSON.stringify handles it)
- Scope cache deletion to claude-mem only, not entire vendor namespace
- Use getWorkerPort() in OpenCodeInstaller instead of hard-coded 37777
- Throw on corrupt JSON in readJsonSafe/readGeminiSettings/Windsurf to prevent data loss
- Fix Cursor install stub to warn instead of silently succeeding
- Fix Gemini uninstall to remove individual hooks within groups, not whole groups
- Update tests for new corrupt-file-throws behavior

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 13:49:14 -07:00
Alex Newman cdffdba97a test: add unit tests for MCP factory, context injection, JSON utils, and non-TTY install
59 tests across 4 files covering:
- context-injection: tag injection, replacement, headerLine support, idempotency
- json-utils: missing/valid/corrupt JSON handling with generic types
- mcp-integrations: factory function, process.execPath, idempotency, merge behavior
- install-non-tty: isInteractive detection, runTasks fallback, log wrapper

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 00:39:02 -07:00
Alex Newman 2495f98496 refactor: consolidate MCP factory, add non-TTY support, auto-detect transcript watchers
- Phase 1: Replace 5 duplicate MCP installers with config-driven factory, extract
  shared context-injection and json-utils utilities, fix process.execPath usage
- Phase 2: Add non-TTY fallback for @clack/prompts to prevent ENOENT in CI/Docker
- Phase 3: Wire GeminiCliHooksInstaller through hook command framework with adapter
- Phase 4: Auto-start transcript watchers on worker boot when config exists

Net -107 lines via DRY consolidation of duplicated installer logic.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 00:35:55 -07:00
Alex Newman a2ac116aac fix: move summary wait + session-complete into Stop hook to prevent lost summaries
SessionEnd has a 1.5s hardcoded cap from Claude Code (CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS),
making it unsuitable for waiting on async work. Previously, the Stop hook would fire-and-forget
the summarize request, then SessionEnd would immediately call deleteSession — aborting the SDK
agent mid-summary.

Now the Stop hook (120s timeout, no cap) owns the full lifecycle:
1. Queue summarize request
2. Poll new GET /api/sessions/status endpoint until queue drains
3. Call /api/sessions/complete after summary finishes

SessionEnd is now a true fire-and-forget fallback (process.exit(0) immediately).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 14:05:53 -07:00
Alex Newman 8265fc7aa1 Merge remote-tracking branch 'origin/thedotmack/npx-gemini-cli' into thedotmack/npx-gemini-cli
Resolve merge conflicts in adapter index, gemini-cli adapter, and rebuilt CJS artifacts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 13:47:49 -07:00
Alex Newman 76a880a3d6 feat: update install CLI, ESM compat, and Gemini CLI docs
Fixes CursorHooksInstaller ESM compatibility, updates install command
with improved path resolution, and refreshes built plugin artifacts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 12:38:45 -07:00
suyua9 8c03704246 docs: tighten session architecture wording 2026-04-04 01:38:49 +08:00
suyua9 91f73a83bc docs: align session architecture with current semantics 2026-04-04 01:24:48 +08:00
Octopus c74101b7f7 fix: handle bare filenames in regenerate-claude-md.ts (fixes #1514) 2026-04-03 10:07:11 +08:00
Octopus 1b5d1a1234 fix: handle bare filenames in path-utils.ts isDirectChild 2026-04-03 10:07:03 +08:00
Octopus c4146cca67 fix: provide empty JSON fallback when stdin is not piped (fixes #1560) 2026-04-03 10:03:29 +08:00
ming eea9c100ba fix: harden plugin manifest sync script 2026-04-02 20:15:26 +08:00
ming 16f79d6f71 chore: sync plugin manifest metadata from package 2026-04-02 20:07:00 +08:00
ming a74ff0034f fix: add Codex plugin manifest for discoverability 2026-04-02 18:44:59 +08:00
Alex Newman a66b98bcdd fix: strip <system-reminder> tags from persisted memory and DRY up regex
System reminders (CLAUDE.md contents, deferred tool lists) were being
stored in memory observations. Add system-reminder to the tag stripping
pipeline alongside <private> and <system_instruction>, and extract the
duplicated regex into a shared SYSTEM_REMINDER_REGEX constant.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 00:25:13 -07:00
Jarvis bd47a919a8 fix: use cmd /c to execute bun.cmd on Windows
Instead of using shell:true with spawn(), use cmd.exe as the command
with /c flag to properly execute bun.cmd on Windows.

Without this, spawn() with shell:true fails because cmd.exe doesn't
know how to handle the bun shell script directly.

Fixes: Stop hook "Failed to start Bun: spawn bun ENOENT"
2026-04-02 13:06:12 +08:00
Jarvis 4d4b0a2f24 fix: prefer bun.cmd over bun shell script on Windows
Windows npm installs both bun (shell script) and bun.cmd (batch file).
When spawning bun, cmd.exe cannot execute the shell script directly.
This change makes findBun() return the full path to bun.cmd on Windows.

Fixes: Stop hook "spawn bun ENOENT" on Windows
2026-04-02 13:00:15 +08:00
Jarvis 472d302133 fix: add shell:true on Windows to spawn bun from npm
Windows npm installs bun as a shell script (C:\Users\...\AppData\Roaming\npm\bun),
not a native executable. Without shell:true, spawn() fails with ENOENT
when trying to execute it.

Fixes Stop hook failure: "Failed to start Bun: spawn bun ENOENT"
2026-04-02 12:50:56 +08:00
Alex Newman 303aafa64b chore: rebuild after merge from main
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 16:11:49 -07:00
Alex Newman 67645041fa Merge main into thedotmack/file-read-timeline-inject
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 16:11:41 -07:00
Ousama Ben Younes d8eb2fa9f9 fix: resolve hook failures when CLAUDE_PLUGIN_ROOT is not injected (#1533)
The fallback path for CLAUDE_PLUGIN_ROOT was pointing to the old
marketplaces install location which no longer exists. Hooks now first
try to find the latest versioned cache directory
(~/.claude/plugins/cache/thedotmack/claude-mem/<version>/) using ls -dt,
with the marketplaces path kept as a final fallback.

This mirrors the self-resolution pattern already used in bun-runner.js
(resolve(__bun_runner_dirname, '..')) but at the shell level, so node
can find bun-runner.js in the first place.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 07:01:37 +00:00
Ousama Ben Younes 93a30c5c8f fix: skip parseSummary false positives with no sub-tags (#1360)
When an observation response accidentally contains a <summary> tag with
plain text (no <request>/<investigated>/etc. sub-tags), parseSummary was
creating empty SESSION SUMMARY records with all fields as empty strings.

Add an all-null guard AFTER field extraction: if none of the 5 sub-tags
matched, the <summary> match is a false positive and we return null.

This is distinct from the commented-out validation above (which rejected
summaries with SOME missing fields). We only reject when ALL are absent —
real partial summaries are still saved per the maintainer's explicit note.

Closes #1360

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-01 06:51:33 +00:00
Ousama Ben Younes 2a304d59eb fix: handle bare path strings in files_modified/files_read columns (#1359)
JSON.parse('/path/to/file') throws SyntaxError, crashing the viewer and
any code reading observations with legacy bare-path data in those columns.

- Add parseFileList() helper in observations/files.ts — tries JSON.parse,
  falls back to wrapping bare strings in an array
- Replace unsafe JSON.parse calls in files.ts, SessionStore.ts, ChromaSync.ts
- Add 9 unit tests covering null, empty, valid JSON, bare paths, invalid JSON

Closes #1359

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-01 06:17:35 +00:00
Ousama Ben Younes 12501412b9 fix: persist session completion to database in completeByDbId (#1532)
completeByDbId only cleaned up in-memory state, leaving sdk_sessions rows
with status='active' and completed_at=NULL indefinitely. Ghost sessions
accumulated and exhausted the agent pool, causing 60s timeout errors.

- Add SessionStore.markSessionCompleted() to set status/completed_at/completed_at_epoch
- Call it at the start of completeByDbId before in-memory cleanup
- Inject SessionStore into SessionCompletionHandler via constructor
- Add 4 tests covering status, timestamps, isolation, and non-existent IDs

Closes #1532

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-01 06:02:14 +00:00
Ousama Ben Younes fb8c9dbdbe fix: prevent shell injection in summary workflow (#1285)
The gh issue comment command was interpolating the LLM response via
${{ steps.inference.outputs.response }} directly in the shell, allowing
single-quote escaping if the response contained untrusted content.
RESPONSE was already declared as an env var but unused — now using it.

Closes #1285

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-01 05:13:53 +00:00
Ousama Ben Younes b81281fd6c fix: update default model from claude-sonnet-4-5 to claude-sonnet-4-6 (#1390)
CLAUDE_MEM_MODEL defaulted to the deprecated claude-sonnet-4-5 across source,
installer, tests, and documentation. Updated all references to claude-sonnet-4-6.

Closes #1390

Co-Authored-By: Claude <noreply@anthropic.com>
2026-03-31 22:42:23 +00:00
Kevin Crawley 247d287bdc Fix error log message to use dynamic target filename 2026-03-31 06:20:33 -05:00
Kevin Crawley 2a6c9ea2b7 Add CLAUDE.local.md support via CLAUDE_MEM_FOLDER_USE_LOCAL_MD setting
When CLAUDE_MEM_FOLDER_USE_LOCAL_MD is set to 'true' in settings,
claude-mem writes auto-generated context to CLAUDE.local.md instead
of CLAUDE.md. This separates personal machine-generated context from
shared project instructions, aligning with Claude Code's native
CLAUDE.local.md convention where:

- CLAUDE.md = team-shared project instructions (checked into git)
- CLAUDE.local.md = personal/local context (gitignored)

Changes:
- Add CLAUDE_MEM_FOLDER_USE_LOCAL_MD setting (default: false)
- Add getTargetFilename() helper to resolve target based on settings
- Update writeClaudeMdToFolder() to accept optional target filename
- Update active-file detection to skip folders with either CLAUDE.md
  or CLAUDE.local.md being actively read/modified (issue #859 compat)
- Add 8 new tests covering filename selection, write behavior,
  content preservation, atomic writes, and active-file detection

Closes #632
2026-03-31 06:20:33 -05:00
Oracle Public Cloud User 4589b34eab fix: decouple mcp health from loopback self-check 2026-03-30 16:37:56 +00:00
GigiTiti-Kai 7fce21c145 fix: deduplicate session init to prevent multiple prompt records
When using the OpenClaw integration, a single user message would produce
3 prompt records because session_start, message_received, after_compaction,
and before_agent_start each independently called /api/sessions/init with
different session keys.

Changes:
- Centralize /api/sessions/init to before_agent_start only
- Add canonical session key unification (sessionKey, conversationId,
  channelId mapped to a single contentSessionId)
- Add 2-second dedup guard for edge cases
- Fix cwd: "" in tool_result_persist (use workspaceDir fallback chain,
  skip + warn if unavailable)
- Add delayed session completion (configurable, default 5s) to avoid
  race with in-flight observations
- Clean up all tracking Maps on session_end and gateway_start

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 23:20:18 +09:00
Ryan Malia b0f1a458cf fix: log warning when readiness times out on reused-worker path (#1491)
Mirror the fresh-spawn path's timeout logging for debugging parity.
CodeRabbit nitpick on PR #1491.

Co-Authored-By: CC <noreply@anthropic.com>
2026-03-30 03:47:08 -07:00
Ryan Malia 83f61177c7 fix: address CodeRabbit review feedback on PR #1491
- Update POST_SPAWN_WAIT test assertion from 5000 to 15000 to match
  the constant change in hook-constants.ts
- Remove redundant readPidFile() from aggressiveStartupCleanup() —
  start() writes the new PID before this runs, so it always returns
  process.pid (already protected)
- Add waitForReadiness() to the reused-worker path in
  ensureWorkerStarted() to prevent concurrent hooks from racing
  past a cold-starting worker's initialization guard

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-30 03:43:36 -07:00
Ryan Malia 88b47f9e9c fix: prevent worker daemon from being killed by its own hooks (#1490)
Three independent fixes for worker daemon instability:

1. Remove version mismatch auto-restart from ensureWorkerStarted() (#1435).
   The marketplace bundle ships with __DEFAULT_PACKAGE_VERSION__ unbaked,
   causing BUILT_IN_VERSION to fall back to "development". This creates a
   100% reproducible mismatch on every hook call, killing a healthy worker
   and often failing to restart. Same pattern across #566, #665, #667,
   #669, #689, #1124, #1145 (8+ releases).

2. Add process.ppid and PID-file PID to aggressiveStartupCleanup()
   exclusions (#1426). Without this, a newly spawned daemon SIGKILLs
   the hook process that spawned it and any already-running worker
   the PID file points to.

3. Increase POST_SPAWN_WAIT from 5s to 15s (#1423). The 5s timeout was
   sized for Linux (<1s startup) but macOS ARM64 cold starts take 6-8s
   with Chroma enabled.
2026-03-30 03:43:36 -07:00
JasonOA888 f86be1ef2b fix(project-name): expand ~ to home directory before project resolution
Fixes #1478

When a terminal reports cwd as '~' or '~/subpath' instead of the full
path, getProjectName() fell through to the 'unknown-project' fallback
because path.basename('~') returns '~' as-is.

Added expandTilde() helper that resolves leading ~ to os.homedir(),
called in both getProjectName() and getProjectContext() before path
operations and worktree detection.
2026-03-30 09:12:23 +08:00
Alex Newman d06882126f docs: update CHANGELOG.md for v10.6.3
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 19:50:03 -07:00
Alex Newman ddb57ea598 chore: bump version to 10.6.3
Publish to npm / publish (push) Has been cancelled
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
v10.6.3
2026-03-28 19:49:24 -07:00
Alex Newman 6885bdb019 Merge pull request #1518 from thedotmack/thedotmack/patch-plan-issues
fix: patch 7 critical bugs for v10.6.3
2026-03-28 19:48:43 -07:00
Alex Newman 0321f4266d fix: remove import.meta.url banner from CJS files run by Node.js
The MCP server (#!/usr/bin/env node) and context generator run under
Node.js, where import.meta.url throws SyntaxError in CJS mode. Only
the worker-service needs the banner since it runs under Bun.

CJS files under Node.js already have __dirname/__filename natively.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 18:32:43 -07:00
Alex Newman 80d1deedbe fix: address PR review feedback from CodeRabbit
- Add sessionId to summarize.ts warning log for easier triage
- Add APPROVED OVERRIDE annotation to Windows spawn catch block

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 15:34:42 -07:00
Alex Newman 07ab7000a8 fix: patch 7 critical bugs affecting all non-dev-machine users and Windows
1. Fix esbuild inlining build-machine __dirname as string literal — use
   CJS-compatible runtime banner with require("node:url").fileURLToPath
   across worker-service, mcp-server, and context-generator builds.

2. Fix isMainModule check missing .cjs extension and Windows backslash
   path normalization.

3. Wrap extractLastMessage in try-catch to prevent infinite Stop hook
   feedback loop on malformed transcripts (exit 0 instead of exit 2).

4. Replace heavy SessionEnd hook (Node→Bun→1.7MB CJS→HTTP) with
   lightweight inline node -e one-liner (~200ms vs >1s).

5. Add 7 Gemini/OpenRouter error patterns to unrecoverablePatterns
   circuit breaker to prevent 77K+ retry loops on expired API keys.

6. Preserve CLAUDE_CODE_OAUTH_TOKEN and CLAUDE_CODE_GIT_BASH_PATH in
   sanitizeEnv instead of stripping them with the CLAUDE_CODE_ prefix.

7. Use PowerShell -EncodedCommand for spawnDaemon to fix path quoting
   when Windows usernames contain spaces.

Closes #1515, #1495, #1475, #1465, #1500, #1513, #1512, #1450, #1460,
#1486, #1449, #1481, #1451, #1480, #1453, #1445

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 15:20:29 -07:00
nimesh-kumar-sh a48bf89963 fix: fail worker-start hook if worker never becomes healthy
Address CodeRabbit review: add a final health check after the retry
loop so genuine worker startup failures surface as hook errors instead
of being silently masked.
2026-03-27 13:03:05 -07:00
nimesh-kumar-sh 368daddd88 fix(bun-runner): treat signal-based exits for 'start' as success
Defense-in-depth for #1505. When the 'start' subcommand forks a daemon,
the parent bun process may be killed by signal (exit > 128). If the
close handler fires, treat this as success since the daemon started fine.

Note: the primary fix is in hooks.json since the SIGKILL often kills
the entire process group before this handler fires.
2026-03-27 12:52:36 -07:00
nimesh-kumar-sh ed444dfec7 fix: SessionStart hooks fail on cold start due to worker race condition
The worker-start hook's `start` subcommand forks a daemon then SIGKILLs
its own process group, killing bun-runner.js before it can report exit 0.
Since all SessionStart hooks run in parallel, the context hook also fails
because the worker isn't listening yet.

Fix:
- worker-start: continue after the SIGKILL via `;`, poll the worker
  health endpoint until ready, then output valid JSON (exit 0)
- context: wait for worker health before attempting to fetch context

Fixes #1505
2026-03-27 12:52:02 -07:00
Alan T Miller 4aa7119d7d fix: remove dead USER_MESSAGE_ONLY exit code that caused SessionStart hook errors
The USER_MESSAGE_ONLY (exit code 3) constant was used by the old
user-message-hook.js (removed in the hooks refactor). Claude Code only
recognizes exit codes 0 (success) and 2 (blocking error) — any other
non-zero exit code is treated as a hook failure, causing the
"SessionStart:startup hook error" message on every session start for
users still running v8.x.

This removes the dead constant and improves the exit code documentation
to prevent reintroduction.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 21:59:53 -07:00
Conductor 5621b67ccd Saving uncommitted changes before archiving 2026-03-26 19:35:27 -07:00
79475432@qq.com 9cfa57d498 fix: use null-byte delimiter in observation content hash to prevent collisions
Fields concatenated without separators allowed different tuples to produce
identical hashes (e.g. session="ab", title="cd" vs session="abc", title="d").
This could cause legitimate observations to be silently deduplicated.

Join with \x00 so field boundaries are unambiguous.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 17:16:17 +08:00
Alex Newman a656af2bff feat: improve Gemini CLI timeline display by stripping ANSI colors and providing markdown fallback 2026-03-25 23:51:56 -07:00
zengyuzhi fe8c65a8cd feat(openclaw): add workerHost config for Docker deployments
When the OpenClaw gateway runs in Docker and the claude-mem worker runs
on the host, localhost:37777 is unreachable from inside the container.

Add a workerHost config option (default: 127.0.0.1) so users can set it
to host.docker.internal for Docker-based deployments.

Changes:
- Add workerHost to ClaudeMemPluginConfig interface
- Read workerHost from plugin config in plugin entry point
- Update workerBaseUrl to use configurable host
- Add workerHost to openclaw.plugin.json config schema
- Update startup log to show configured host
2026-03-25 14:40:33 +08:00
huakson 4f6fb9e614 fix: address platform source review feedback
Tighten platform source persistence so legacy callers cannot silently relabel existing sessions, repair migration 24 when schema_versions drifts from the real schema, and polish the follow-up UI/error-handler review nits.

- only backfill platform_source when it is blank and raise on explicit source conflicts for an existing session
- make migration 24 verify both the sdk_sessions column and its index before treating it as applied
- expose platform_source from the functional session getters and add regression tests for source preservation and schema drift recovery
- add the required APPROVED OVERRIDE annotation for centralized HTTP error translation
- keep mobile source pills on a single horizontal row
2026-03-24 10:46:48 -03:00
huakson 2b60dd2932 feat: isolate Claude and Codex session sources
Persist platform_source across session creation, transcript ingestion, API query paths, and viewer state so Claude and Codex data can coexist without bleeding into each other.

- add platform-source normalization helpers and persist platform_source in sdk_sessions via migration 24 with backfill and indexing
- thread platformSource through CLI hooks, transcript processing, context generation, pagination, search routes, SSE payloads, and session management
- expose source-aware project catalogs, viewer tabs, context preview selectors, and source badges for observations, prompts, and summaries
- start the transcript watcher from the worker for transcript-based clients and preserve platform source during Codex ingestion
- auto-start the worker from the MCP server for MCP-only clients and tighten stdio-driven cleanup during shutdown
- keep createSDKSession backward compatible with existing custom-title callers while allowing explicit platform source forwarding
2026-03-24 08:46:18 -03:00