Skip to content

fix(agentdb): add delete API — closes #150 (ruflo#1784 / RuVector#427 chain)#151

Merged
ruvnet merged 1 commit intomainfrom
fix/issue-150-agentdb-delete-api
May 6, 2026
Merged

fix(agentdb): add delete API — closes #150 (ruflo#1784 / RuVector#427 chain)#151
ruvnet merged 1 commit intomainfrom
fix/issue-150-agentdb-delete-api

Conversation

@ruvnet
Copy link
Copy Markdown
Owner

@ruvnet ruvnet commented May 6, 2026

Summary

Closes the agentdb-side gap from this chain:

The native @ruvector/graph-node binding exposes only createNode / createEdge / createHyperedge / searchHyperedges as documented methods, but GraphDatabase.prototype.query(cypher) is also live. We implement delete by routing through Cypher so consumers get a delete API today without waiting for binding-level methods.

What ships

New on GraphDatabaseAdapter (packages/agentdb/src/backends/graph/GraphDatabaseAdapter.ts)

Method Notes
deleteNode(id, { cascade?: boolean }): { deletedNode, deletedEdges } Counts incident edges before delete so the count is accurate regardless of binding stats. cascade: false refuses with a typed error when edges exist (matches RuVector#427 spec).
deleteEdge(id): { deleted } Endpoints stay intact.
deleteHyperedge(id): { deleted } Match scoped with :HYPEREDGE to disambiguate from regular relationships.
deleteEdgesByEndpoints(from, to, label?): { deleted } Saves callers from materialising every edge id when they want to scrub a (source, target, label) tuple.
escapeId / escapeLabel Cypher-injection guards — labels validated against /^[A-Za-z_][A-Za-z0-9_]*$/ so 'evil; DROP' throws instead of slipping into the query.

New on ReflexionMemory

Tests

packages/agentdb/tests/unit/controllers/ReflexionMemory-delete.test.ts — 10 tests, all passing:

  • 3 ReflexionMemory.deleteEpisode tests against an in-memory SQL fake
  • 7 GraphDatabaseAdapter Cypher-emission tests against a CypherSpy that records every query() call:
    • DETACH DELETE wiring + accurate edge count
    • cascade: false refusal with edge count
    • edge-by-id
    • hyperedge :HYPEREDGE label scoping
    • endpoint-tuple delete
    • label injection guard
    • id escaping for embedded quotes/backslashes
cd packages/agentdb && npx vitest run tests/unit/controllers/ReflexionMemory-delete.test.ts
Test Files  1 passed (1)
     Tests  10 passed (10)

The existing 23-test verification suite for the prior issue fixes (#145, #146, #102, #110, #118/119, #128, #129) is also still passing — no regressions.

Why Cypher and not bind-level

The native binding doesn't expose deleteNode / deleteEdge / deleteHyperedge even on the latest published @ruvector/graph-node@2.0.4. RuVector#427 is closed but those methods aren't on the registry yet. Rather than block on republishing the binding, we route through Cypher (MATCH (n {id: $id}) DETACH DELETE n RETURN count(n)) — same end result, no upstream-publish dependency. When the binding ships native methods, this adapter can switch to those without breaking the public API.

Downstream

Once this is published as agentdb@3.0.0-alpha.13, ruvnet/ruflo#1789's stub branches at bridgeDeleteCausalNode / bridgeDeleteCausalEdge can re-target their primary path at graphAdapter.deleteNode / .deleteEdge. The SQL fallback then becomes a true fallback — only fires when the graph backend isn't loaded.

Closes #150

🤖 Generated with claude-flow

…y.deleteEpisode (#150)

Closes the agentdb-side gap from ruvnet/ruflo#1784 and ruvnet/RuVector#427:
the GraphDatabaseAdapter wraps @ruvector/graph-node which exposes only
create/search primitives, but its query() method accepts arbitrary Cypher
— so we can implement delete via DETACH DELETE today without waiting for
binding-level methods to be republished.

New on GraphDatabaseAdapter:
- deleteNode(id, { cascade?: boolean }): { deletedNode, deletedEdges }
  Counts incident edges before delete so the caller gets an accurate
  edge-removal count regardless of binding stats. cascade: false refuses
  when incident edges exist (matches RuVector#427 spec).
- deleteEdge(id): { deleted }
- deleteHyperedge(id): { deleted } — scopes the match with :HYPEREDGE
- deleteEdgesByEndpoints(from, to, label?): { deleted } — saves callers
  from materialising every edge id before scrubbing a tuple
- escapeId / escapeLabel: Cypher-injection guards for ids that may carry
  user-supplied content. Labels are validated against
  /^[A-Za-z_][A-Za-z0-9_]*$/ so something like 'evil; DROP' throws
  instead of slipping into the query.

New on ReflexionMemory:
- deleteEpisode(id: number | string): boolean
  Mirrors the dual-write pattern from #128 in reverse — routes through
  graph adapter / generic graph backend / vector backend (when present)
  and ALSO purges SQL episodes / episode_embeddings rows so durable
  storage stays in sync. Best-effort across backends; returns true if any
  backend acknowledged the delete.

Tests (10): tests/unit/controllers/ReflexionMemory-delete.test.ts
- 3 ReflexionMemory.deleteEpisode tests against in-memory SQL fake
- 7 GraphDatabaseAdapter Cypher-emission tests against a CypherSpy that
  records every query() call: covers DETACH DELETE wiring, cascade refusal,
  edge-by-id, hyperedge label scoping, endpoint-tuple delete, label
  injection guard, id escaping for embedded quotes/backslashes.

Verified:
  cd packages/agentdb && npx vitest run tests/unit/controllers/ReflexionMemory-delete.test.ts
    Test Files  1 passed (1)
         Tests  10 passed (10)

  cd agentic-flow && npx vitest run tests/issue-fixes.test.ts
    Test Files  1 passed (1)
         Tests  23 passed (23)   (still passing — no regressions)

Closes #150

Co-Authored-By: claude-flow <ruv@ruv.net>
@ruvnet ruvnet merged commit c2af4dc into main May 6, 2026
@ruvnet ruvnet deleted the fix/issue-150-agentdb-delete-api branch May 6, 2026 14:18
ruvnet added a commit that referenced this pull request May 6, 2026
Ships the delete API from PR #151 (#150) to npm:

  agentdb         3.0.0-alpha.12 → 3.0.0-alpha.13
  agentic-flow    2.0.9          → 2.0.10
                  dependencies.agentdb: ^3.0.0-alpha.13

Live-verified via fresh npm install agentic-flow@2.0.10:
  └─┬ agentic-flow@2.0.10
    └── agentdb@3.0.0-alpha.13

  ✓ deleteNode / deleteEdge / deleteHyperedge / deleteEdgesByEndpoints
    compiled into published agentdb/dist/src/backends/graph/GraphDatabaseAdapter.js
  ✓ deleteEpisode compiled into published
    agentdb/dist/src/controllers/ReflexionMemory.js
  ✓ npm dist-tags: agentdb latest=3.0.0-alpha.13, agentic-flow latest=2.0.10

Closes the agentdb side of:
  - ruvnet/ruflo#1784  (downstream MCP-tool layer)
  - ruvnet/RuVector#427 (binding-level — still pending native publish)

ruflo PR #1789 can now re-target bridgeDeleteCausalNode / bridgeDeleteCausalEdge
at graphAdapter.deleteNode / .deleteEdge.

Co-Authored-By: claude-flow <ruv@ruv.net>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

agentdb: GraphDatabaseAdapter has no delete methods — blocks downstream re-indexing (ruflo#1784, RuVector#427)

1 participant