feat: add Cortex entity and graph tools#35
Conversation
📝 WalkthroughWalkthroughThis PR adds three new read-only Cortex entity and relationship graph tools to the plugin, implements memory injection truncation logging to address silent context-cap drops, extends the CortexClient with corresponding API wrappers, and validates all changes through comprehensive tests and updated documentation. ChangesCortex Entity/Graph Tools and Memory Truncation Logging
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint skipped: no ESLint configuration detected in root package.json. To enable, add Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/index.ts`:
- Around line 1714-1718: The early return when lines.length <= 2 hides the
truncation log/footer: if truncatedByCharCap is true we should still emit the
info and append the footer before returning. Modify the block around the check
(the code using truncatedByCharCap, injectedCount, totalCount, charCount,
maxChars and the lines.push footer) so that when lines.length <= 2 you only
early-return after logging the console.info and appending the `[${injectedCount}
of ${totalCount} memories shown — use cortex_search for more]` line when
truncatedByCharCap is true (apply the same change to the other occurrence around
lines 1755-1759 / v1 and v2).
- Around line 679-687: The listEntities call is sending both page/per_page and
limit/offset which can conflict; remove the derived page and per_page entries
from the params object so only limit and offset are sent. Edit the params
construction in listEntities (the ownerParams call that currently includes page:
String(page) and per_page: String(limit)) and delete those two keys, leaving
per-page pagination to the provided limit/offset variables and the existing
limit/offset strings.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: ccc5b5f9-81cf-40c2-9a81-a93de42f5b74
⛔ Files ignored due to path filters (15)
dist/__tests__/core-entity-graph-tools.test.d.tsis excluded by!**/dist/**dist/__tests__/core-entity-graph-tools.test.d.ts.mapis excluded by!**/dist/**,!**/*.mapdist/__tests__/core-entity-graph-tools.test.jsis excluded by!**/dist/**dist/__tests__/core-entity-graph-tools.test.js.mapis excluded by!**/dist/**,!**/*.mapdist/__tests__/memory-context-format.test.jsis excluded by!**/dist/**dist/__tests__/memory-context-format.test.js.mapis excluded by!**/dist/**,!**/*.mapdist/__tests__/owner-context.test.jsis excluded by!**/dist/**dist/__tests__/owner-context.test.js.mapis excluded by!**/dist/**,!**/*.mapdist/__tests__/plugin-manifest-parity.test.jsis excluded by!**/dist/**dist/__tests__/plugin-manifest-parity.test.js.mapis excluded by!**/dist/**,!**/*.mapdist/index.d.tsis excluded by!**/dist/**dist/index.d.ts.mapis excluded by!**/dist/**,!**/*.mapdist/index.jsis excluded by!**/dist/**dist/index.js.mapis excluded by!**/dist/**,!**/*.mapdist/openclaw.plugin.jsonis excluded by!**/dist/**
📒 Files selected for processing (9)
README.mddocs/cortex-core-tools.mdopenclaw.plugin.jsonpackage.jsonsrc/__tests__/core-entity-graph-tools.test.tssrc/__tests__/memory-context-format.test.tssrc/__tests__/owner-context.test.tssrc/__tests__/plugin-manifest-parity.test.tssrc/index.ts
| const limit = clampNumber(options.limit, 50, 1, 200); | ||
| const offset = clampNumber(options.offset, 0, 0, 1000000); | ||
| const page = Math.floor(offset / limit) + 1; | ||
| const params = this.ownerParams({ | ||
| page: String(page), | ||
| per_page: String(limit), | ||
| limit: String(limit), | ||
| offset: String(offset), | ||
| }); |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify which pagination contract is documented/tested in this repo.
rg -n --type=md -C2 '/api/v1/entities|entity|entities|limit|offset|page|per_page'
rg -n --type=ts -C3 'listEntities\\(|cortex_entities_list|max entities|offset|page|per_page'Repository: electricsheephq/evaos-cortex-plugin
Length of output: 2464
🏁 Script executed:
#!/bin/bash
# First, let's read the file to see the actual listEntities implementation
sed -n '660,700p' src/index.ts | cat -n
# Then search for any API documentation files
fd -e md -e txt | xargs grep -l "listEntities\|entities.*limit\|entities.*offset\|entities.*page" 2>/dev/null | head -20Repository: electricsheephq/evaos-cortex-plugin
Length of output: 1579
🏁 Script executed:
#!/bin/bash
# Search for listEntities definition and usage
rg -n "listEntities" --type=ts -B5 -A20 | head -100
# Search for test files that test listEntities
fd -e test.ts -e spec.ts | xargs grep -l "listEntities" 2>/dev/nullRepository: electricsheephq/evaos-cortex-plugin
Length of output: 63
🏁 Script executed:
#!/bin/bash
# Look for backend API endpoint documentation or configuration
fd -e md -e json -e yaml | xargs grep -l "entities" 2>/dev/null | head -10Repository: electricsheephq/evaos-cortex-plugin
Length of output: 180
🏁 Script executed:
#!/bin/bash
# Read documentation files that may specify API parameters
cat docs/cortex-core-tools.md | head -100Repository: electricsheephq/evaos-cortex-plugin
Length of output: 1060
🏁 Script executed:
#!/bin/bash
# Search for any backend configuration or API specs
rg -n "api/v1/entities" --type=ts --type=md -B3 -A3Repository: electricsheephq/evaos-cortex-plugin
Length of output: 61
🏁 Script executed:
#!/bin/bash
# Look for tests of listEntities
rg -n "listEntities" --type=ts -B2 -A10Repository: electricsheephq/evaos-cortex-plugin
Length of output: 61
🏁 Script executed:
#!/bin/bash
# Search for any comment or documentation about the API parameters
rg -n "page|per_page|limit|offset" --type=md | grep -i entityRepository: electricsheephq/evaos-cortex-plugin
Length of output: 61
🏁 Script executed:
#!/bin/bash
# Search more broadly for test files
fd -type f -name "*.test.*" -o -name "*.spec.*" -o -name "*test*" | head -20Repository: electricsheephq/evaos-cortex-plugin
Length of output: 250
🏁 Script executed:
#!/bin/bash
# Look for any usage of listEntities in the codebase
rg "listEntities" --type=tsRepository: electricsheephq/evaos-cortex-plugin
Length of output: 61
🏁 Script executed:
#!/bin/bash
# Search for comments about pagination or the API endpoint
rg "page|per_page|limit|offset" --type=ts | grep -i "api\|entities\|pagina" | head -30Repository: electricsheephq/evaos-cortex-plugin
Length of output: 61
🏁 Script executed:
#!/bin/bash
# Check if there's any backend API spec or swagger/openapi files
fd -type f \( -name "*.openapi*" -o -name "*swagger*" -o -name "*.yaml" -o -name "*.yml" \)Repository: electricsheephq/evaos-cortex-plugin
Length of output: 250
🏁 Script executed:
#!/bin/bash
# List test files more simply
find . -name "*.test.ts" -o -name "*.spec.ts" -o -name "*.test.js" -o -name "*.spec.js" 2>/dev/null | head -20Repository: electricsheephq/evaos-cortex-plugin
Length of output: 682
🏁 Script executed:
#!/bin/bash
# Try broader search for listEntities without type restriction
rg "listEntities" -iRepository: electricsheephq/evaos-cortex-plugin
Length of output: 393
🏁 Script executed:
#!/bin/bash
# Search for all references to the endpoint
rg "/api/v1/entities"Repository: electricsheephq/evaos-cortex-plugin
Length of output: 277
🏁 Script executed:
#!/bin/bash
# Look at the actual file structure
ls -la
find . -name "*.md" | head -10Repository: electricsheephq/evaos-cortex-plugin
Length of output: 1062
🏁 Script executed:
#!/bin/bash
# Read the core entity graph tools test to understand pagination expectations
cat src/__tests__/core-entity-graph-tools.test.tsRepository: electricsheephq/evaos-cortex-plugin
Length of output: 2138
🏁 Script executed:
#!/bin/bash
# Check git history for this change
git log --oneline src/index.ts | head -10
git log -p --follow -S "page = Math.floor" -- src/index.ts | head -50Repository: electricsheephq/evaos-cortex-plugin
Length of output: 129
🏁 Script executed:
#!/bin/bash
# Search for any comments explaining pagination parameters
rg -n "page|per_page|limit|offset|pagina" src/index.ts | grep -E "//|/\*"Repository: electricsheephq/evaos-cortex-plugin
Length of output: 180
🏁 Script executed:
#!/bin/bash
# Check if there are references to external Cortex documentation
rg "cortex|github|api" README.md | grep -i apiRepository: electricsheephq/evaos-cortex-plugin
Length of output: 353
🏁 Script executed:
#!/bin/bash
# Look at the full listEntities method with more context
sed -n '670,710p' src/index.ts | cat -nRepository: electricsheephq/evaos-cortex-plugin
Length of output: 1594
🏁 Script executed:
#!/bin/bash
# Final check: look at the PR or commit message for context
git log --format="%B" -1 43a112fRepository: electricsheephq/evaos-cortex-plugin
Length of output: 122
🏁 Script executed:
#!/bin/bash
# Check if there are any mocks or fixtures that show expected API responses
find . -name "*.json" -o -name "*.fixture" | xargs grep -l "entities\|page\|offset" 2>/dev/null | head -5Repository: electricsheephq/evaos-cortex-plugin
Length of output: 150
Remove redundant page/per_page pagination parameters from the entities request.
The listEntities method sends both page/per_page and limit/offset parameters to /api/v1/entities. For offsets not divisible by limit, these schemes reference different slices of data. If the backend prioritizes one scheme, the result may be inconsistent with caller intent.
Since listEntities accepts limit and offset as inputs, keep those parameters and remove the derived page and per_page.
Suggested fix
async listEntities(options: {
@@
} = {}) {
const limit = clampNumber(options.limit, 50, 1, 200);
const offset = clampNumber(options.offset, 0, 0, 1000000);
- const page = Math.floor(offset / limit) + 1;
const params = this.ownerParams({
- page: String(page),
- per_page: String(limit),
limit: String(limit),
offset: String(offset),
});🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/index.ts` around lines 679 - 687, The listEntities call is sending both
page/per_page and limit/offset which can conflict; remove the derived page and
per_page entries from the params object so only limit and offset are sent. Edit
the params construction in listEntities (the ownerParams call that currently
includes page: String(page) and per_page: String(limit)) and delete those two
keys, leaving per-page pagination to the provided limit/offset variables and the
existing limit/offset strings.
| if (lines.length <= 2) return ""; | ||
| if (truncatedByCharCap) { | ||
| console.info(`[cortex] memories-injected=${injectedCount}/${totalCount} chars=${charCount}/${maxChars}`); | ||
| } | ||
| lines.push(`[${injectedCount} of ${totalCount} memories shown — use cortex_search for more]`); |
There was a problem hiding this comment.
Char-cap truncation is still silent when zero memories fit.
If the first candidate exceeds maxChars, truncatedByCharCap becomes true but the early return "" runs before logging/footer, so truncation remains invisible.
Suggested fix (apply same pattern in v1 and v2)
- if (lines.length <= 2) return "";
- if (truncatedByCharCap) {
+ if (truncatedByCharCap) {
console.info(`[cortex] memories-injected=${injectedCount}/${totalCount} chars=${charCount}/${maxChars}`);
}
+ if (lines.length <= 2) return "";Also applies to: 1755-1759
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/index.ts` around lines 1714 - 1718, The early return when lines.length <=
2 hides the truncation log/footer: if truncatedByCharCap is true we should still
emit the info and append the footer before returning. Modify the block around
the check (the code using truncatedByCharCap, injectedCount, totalCount,
charCount, maxChars and the lines.push footer) so that when lines.length <= 2
you only early-return after logging the console.info and appending the
`[${injectedCount} of ${totalCount} memories shown — use cortex_search for
more]` line when truncatedByCharCap is true (apply the same change to the other
occurrence around lines 1755-1759 / v1 and v2).
Summary
cortex_entities_list,cortex_entity_detail, andcortex_graph_queryowner_idorX-Owner-IdpathIssue alignment
<relevant-memories>hitsmaxInjectionCharsand truncates injected rowsValidation
npm testgit diff --checkNotes
ownerIdMode: configuredremains the existing self-host escape hatch only.Summary by CodeRabbit
New Features
Documentation