mirror of
https://github.com/rohitg00/agentmemory.git
synced 2026-09-14 20:16:33 +08:00
dependabot/github_actions/actions/setup-node-7
2 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
5023cf3ccb |
fix(memory): honest memory_forget reporting + lesson delete path (#1132)
* fix(memory): guard mem::forget delete/count on record existence
Calling mem::forget with a lesson id (lsn_*) deleted a nonexistent key
from the memories keyspace, counted it, and reported success. Guard the
delete, index cleanup, and counter on the kv.get result, matching the
mem::governance-delete pattern, so nonexistent ids return
{ success: true, deleted: 0 } with no audit row. Closes #1120.
* feat(lessons): add mem::lesson-delete soft-delete function
Register mem::lesson-delete to set deleted: true on a lesson, mirroring
the lesson-strengthen existence guard and audit pattern. Read paths
already filter !l.deleted, and re-saving deleted content creates a fresh
lesson. Adds lesson_delete to the audit operation union.
* feat(mcp): expose memory_lesson_delete tool and REST endpoint
Wire mem::lesson-delete through the MCP tool registry and dispatch
case (memory_lesson_delete) and a POST /agentmemory/lessons/delete REST
route with 400 for a missing lessonId and 404 for a nonexistent lesson.
* chore(consistency): bump tool/endpoint counts to 54/129
Adds memory_lesson_delete to the registry, so update every count surface:
tool-count test, README badge and prose, AGENTS.md stats,
INSTALL_FOR_AGENTS.md, plugin manifests and docs, and the two code
comments this change makes stale. REST endpoint count goes 128 to 129
for the new /agentmemory/lessons/delete route.
* refactor(lessons): simplify 404 mapping and restore decay-delta test
Cast the lesson-delete trigger result once instead of twice inline, and
restore the lastDecayedAt incremental-delta decay test that was dropped
when the lesson-delete describe block was added.
* fix(review): align 404 error shape and regenerate skill references
Review fixes: the lesson-delete REST route now returns the repo-standard
{ error: 'lesson not found' } body on 404 instead of the function-shaped
{ success: false } payload, matching api::memory-by-id. Regenerated the
autogen MCP and REST skill references so memory_lesson_delete and the
lessons/delete route appear in the tables with accurate counts.
* fix(lessons): normalize lessonId at entry points and harden no-op test
Address CodeRabbit review: trim lessonId once at both the MCP dispatch
and REST route before triggering mem::lesson-delete (whitespace-padded
ids previously 404'd or looked up raw), and extend the nonexistent-
memoryId regression test to assert the no-op path performs no kv.delete
and no search-index cleanup.
---------
Co-authored-by: Rohit Ghumare <48523873+rohitg00@users.noreply.github.com>
|
||
|
|
68fddd418e |
feat: OpenCode plugin with 22 auto-capture hooks (closes #236, #244) (#237)
* feat: OpenCode plugin with 22 auto-capture hooks (closes #156) - 22 hook handlers across session lifecycle, messages, tool lifecycle, parts, files, permissions, tasks, commands, and config - Two-layer enrichment pipeline: /context + /enrich via system.transform - Two slash commands: /recall and /remember - Full Claude Code hook parity documented with gap analysis * fix(plugin): use prompt_submit hookType so sessions get firstPrompt mem::observe checks hookType === "prompt_submit" to extract raw.userPrompt and set session.firstPrompt. The plugin was using "user_prompt_submit" which didn't match, so sessions were never named. * fix: address CodeRabbit review feedback on OpenCode plugin - Use ctx.worktree for projectPath instead of opaque project.id - Add Array.isArray guards before output.system/.context.push() - Only delete stashed files after successful enrich POST - Defensive JSON.stringify for undefined tool inputs - Per-session Map-based dedup sets to prevent unbounded growth - Fix negative duration_ms when time.completed is unset - Validate props.file and enforce MAX_STASHED_FILES in file.edited - Deduplicate /summarize call on session idle - Buffer early config events until session.created flushes them - Move contextInjectedSessions.add after successful context fetch - Add DEBUG-gated error logging to network helpers - Guard config input.agent/mcp/provider against non-object types - Fix MCP badge count 44→51 in plugin README * fix: add language identifier to fenced code block in plugin README * fix: store OpenCode session title as summary/firstPrompt on creation * fix(plugin): add session instruction injection and consolidation pipeline (closes #233) Three gaps from the Claude Code plugin port sweep: - Inject agentmemory usage instructions (memory_save, memory_recall, etc.) into the system prompt on first turn via experimental.chat.system.transform, replacing the skills mechanism that OpenCode lacks - Call /crystals/auto and /consolidate-pipeline on session.deleted, mirroring Claude's CONSOLIDATION_ENABLED behavior - Document MEMORY.md vs AGENTS.md architecture comparison (two-hop file bridge vs one-hop direct injection) Gap A (SubagentStop) is unfixable — OpenCode's SubtaskPart type has no completion/result fields. Gap C (Claude MEMORY.md bridge) is intentionally skipped — OpenCode uses direct injection. * fix(plugin): address adversarial code review — 7 critical/high fixes - Guard instructions push with Array.isArray check + fix TOCTOU race by moving contextInjectedSessions.add() before the await - Session-scope stashedFiles via stashFor() helper (was process-global, could cross-contaminate concurrent sessions) - Fix tool prefix in instructions (agentmemory_memory_ not agentmemory_) - Check typeof string before pushing .context into system arrays - Change olderThanDays: 0 → 7 in consolidation fire-and-forget - Increase fire-and-forget timeout from 5s to 30s (consolidation takes minutes, 5s was guaranteed to abort) * fix(plugin): scope stashedFiles.delete(sid) not .clear() on session.deleted * fix(plugin): address round 2 adversarial review — 3 critical fixes - Fix session cross-contamination: file.edited and tool.execute.before now use props.sessionID/input.sessionID fallback instead of only activeSessionId, preventing subagent hijack of parent stash - Fix contextInjectedSessions regression from round 1: move add(sid) to after instructions push (synchronous) but before context fetch (async), so failed /context calls don't permanently skip injection - Fix Map memory leak: prune session entries (stashedFiles, seenSubtaskIds, seenToolCallIds) when session.status goes idle, preventing unbounded growth for crash-killed sessions * fix(plugin): address round 2 remaining medium issues - Enforce MAX_STASHED_FILES cap on chat.message (was missing, could grow unbounded from 50+ file-ref messages) - Remove activeSessionId fallback from session.deleted; log warning when both info.id and sessionID are missing instead of guessing - Add subtaskSetFor/toolCallSetFor lazy-init wrappers matching stashFor pattern; fixes dedup failures for subagents spawned without a preceding session.created event - Guard chat.params against missing input.model (TypeError crash) * fix(plugin): address round 3 adversarial review — 10 HIGH/MEDIUM fixes - Add safeSlice() helper replacing all unsafe (v as string || "").slice() calls; handles objects/BigInt/circular refs via try/catch JSON.stringify - Restore activeSessionId fallback on session.deleted (if both info.id and sessionID missing, fall back like every other handler) - Fix message.updated to check info.id before info.sessionID (matches session.created/session.updated pattern) - Add props.sessionID to message.part.updated fallback chain - Guard undefined callID and subtask ID (prevent dedup silently dropping all subsequent undefined-ID events) - Cap todo.updated at 100 entries (match session.diff's slice pattern) - Fix duration_ms || → ?? (0ms genuine duration no longer falsifies) - Fix extractErrorMessage || → ?? (0/false error values preserved) - Replace extractErrorMessage.slice with safeSlice in retry handler * fix(plugin): address round 4 adversarial review — 6 CRITICAL/HIGH fixes CRITICAL: - Revert message.updated session ID resolution: info.id is the message UUID, not session ID. In message.updated, info is the message object (has role/tokens/modelID), not session info like in session.created. Use props.sessionID || info.sessionID || activeSessionId instead. - Fix post_tool_use_failure -> post_tool_failure: server types.ts defines "post_tool_failure" (no "use_"); compress-synthetic.ts classifies by that exact string. All error observations were misclassified as "other" instead of "error". - Fix contextInjected ordering: move add(sid) after the context fetch completes, not before. If /context times out, session is no longer permanently marked injected, allowing retry on next transform. HIGH: - Add process.cwd() fallback for projectPath (was null, causing silent 400s on every REST call when no workspace) - Guard session.start against null activeSessionId with early return (was sending sessionId: null to API) - Fix duration_ms: use typeof number checks instead of || 0 defaults; missing timing data now correctly reports null instead of 0ms * fix(plugin): address final adversarial blockers --------- Co-authored-by: xuli500177 <62830942+xuli500177@users.noreply.github.com> Co-authored-by: Trip <5579540+cl0ckt0wer@users.noreply.github.com> Co-authored-by: Rohit Ghumare <ghumare64@gmail.com> |