Skip to content

feat(intelligence): add Graph Export#2967

Open
aashir-athar wants to merge 2 commits into
tinyhumansai:mainfrom
aashir-athar:feat/graph-export
Open

feat(intelligence): add Graph Export#2967
aashir-athar wants to merge 2 commits into
tinyhumansai:mainfrom
aashir-athar:feat/graph-export

Conversation

@aashir-athar
Copy link
Copy Markdown
Contributor

@aashir-athar aashir-athar commented May 29, 2026

Summary

Adds a new read-only "Export" tab for data portability: download the entire memory knowledge graph as JSON or CSV. A different kind of feature from the analytics lenses — it's about giving the user ownership of their data ("your memory, yours to keep").

Design

  • Pure deterministic serializers (lib/memory/graphExport.ts): toJsonExport and toCsvExport over a stable {subject, predicate, object, namespace, evidenceCount, updatedAt} projection (malformed rows dropped). The CSV follows RFC 4180 — a field is quoted when it contains a comma, double-quote, CR, or LF; embedded double-quotes are doubled; rows are CRLF-terminated — so entity names with commas/quotes/newlines round-trip safely.
  • Zero new core surface: reuses only memoryGraphQuery. Read-only — the download itself (Blob + object URL + anchor) happens in the container's click handler, never during render, so the engine stays pure.
  • Container/presentational split; the container guards the load with a monotonic request token; the pure panel renders the export-ready count + a JSON/CSV format toggle + a download button. i18n across all 13 locales.

Test plan

  • vitest — 19 tests (engine: projection/malformed-drop/null-namespace/non-finite normalization, JSON round-trip, CSV RFC-4180 escaping for commas/quotes/newlines + CRLF + empty-graph header, format dispatch + MIME; api facade; panel states + format toggle/download callbacks; container load + Blob-download trigger + error)
  • tsc --noEmit — clean
  • eslint — 0 errors
  • prettier --check — clean
  • i18n coverage gate — EXIT 0, no unused graphExport.* keys

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • New Features
    • Added "Graph Export" tab to the Intelligence page allowing users to export knowledge graph data
    • Supports both JSON and CSV export formats with user-selectable format before download
    • Export interface displays exportable relation counts and manages loading, error, and empty states elegantly
    • Includes retry mechanism for handling export failures

Review Change Stack

@aashir-athar aashir-athar requested a review from a team May 29, 2026 18:16
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 29, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f882542a-87d2-4d79-b380-4f3941245933

📥 Commits

Reviewing files that changed from the base of the PR and between 418b6e6 and b3e5324.

📒 Files selected for processing (10)
  • app/src/components/intelligence/GraphExportPanel.test.tsx
  • app/src/components/intelligence/GraphExportPanel.tsx
  • app/src/components/intelligence/GraphExportTab.test.tsx
  • app/src/components/intelligence/GraphExportTab.tsx
  • app/src/lib/i18n/en.ts
  • app/src/lib/memory/graphExport.test.ts
  • app/src/lib/memory/graphExport.ts
  • app/src/pages/Intelligence.tsx
  • app/src/services/api/graphExportApi.test.ts
  • app/src/services/api/graphExportApi.ts
💤 Files with no reviewable changes (6)
  • app/src/pages/Intelligence.tsx
  • app/src/services/api/graphExportApi.test.ts
  • app/src/services/api/graphExportApi.ts
  • app/src/lib/memory/graphExport.ts
  • app/src/lib/memory/graphExport.test.ts
  • app/src/lib/i18n/en.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • app/src/components/intelligence/GraphExportPanel.test.tsx
  • app/src/components/intelligence/GraphExportTab.test.tsx
  • app/src/components/intelligence/GraphExportPanel.tsx
  • app/src/components/intelligence/GraphExportTab.tsx

📝 Walkthrough

Walkthrough

Adds a complete knowledge graph export feature: pure serialization functions (JSON/CSV) with RFC 4180 CSV formatting, an API loader for graph relations, two React components (stateless panel and stateful container), page integration with tab routing, and English localization.

Changes

Knowledge Graph Export Feature

Layer / File(s) Summary
Export data serialization and contracts
app/src/lib/memory/graphExport.ts, app/src/lib/memory/graphExport.test.ts
Defines ExportFormat and ExportRow contracts; implements toExportRows (filters malformed relations, normalizes namespace/numeric fields), toJsonExport, toCsvExport (RFC 4180 escaping), serializeGraph (format dispatcher), and exportMimeType. Tests verify row projection, RFC 4180 quoting/newlines/escaping, JSON parsing, and MIME mapping.
Graph export API facade
app/src/services/api/graphExportApi.ts, app/src/services/api/graphExportApi.test.ts
Calls memoryGraphQuery to load relations, logs relation count via debug, and exposes loadGraphRelations() via graphExportApi object. Tests verify fetch success, error propagation, and API surface.
Export presentational component
app/src/components/intelligence/GraphExportPanel.tsx, app/src/components/intelligence/GraphExportPanel.test.tsx
Stateless GraphExportPanel conditionally renders loading skeleton, error alert with optional retry, empty message, or populated UI with count, format radio-group (JSON/CSV), and download button. Tests cover all four states and callback assertions.
Export container and download orchestration
app/src/components/intelligence/GraphExportTab.tsx, app/src/components/intelligence/GraphExportTab.test.tsx
GraphExportTab loads relations on mount (monotonic request ID for stale handling), computes exportable count, manages format selection, serializes with serializeGraph, creates Blob with MIME type, downloads via temporary anchor with timestamped filename, and revokes URLs. Renders GraphExportPanel with all wired callbacks. Tests mock API, stub URL methods, and validate flows.
Page integration and English localization
app/src/pages/Intelligence.tsx, app/src/lib/i18n/en.ts
Adds GraphExportTab import; extends IntelligenceTab union with 'export'; adds export tab entry to tabs array and conditional render. Introduces memory.tab.export and graphExport.* translation strings (intro, loading, error, retry, empty, count label, format label, options, download button).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • tinyhumansai/openhuman#2931: Both PRs extend the Intelligence page with new tabs (export vs. centrality) and render conditional tab components following the same pattern.

Suggested reviewers

  • graycyrus

Poem

🐰 A graph's journey from data to download,
With JSON and CSV in RFC 4180's flow,
From serialization pure to UI pristine,
The knowledge graph export now shines between,
Facts ready to share, one click to go! 📊✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 63.64% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(intelligence): add Graph Export' clearly and concisely describes the main change—adding a new Graph Export feature to the Intelligence module.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

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

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot added feature Net-new user-facing capability or product behavior. memory Memory store, memory tree, recall, summarization, and embeddings in src/openhuman/memory/. working A PR that is being worked on by the team. labels May 29, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 `@app/src/components/intelligence/GraphExportTab.tsx`:
- Around line 47-54: The blob URL is revoked immediately after anchor.click(),
which can cancel the download; update the download flow in GraphExportTab to
defer revocation like the pattern used in McpInventoryExportTab: create the URL
(url), set anchor.href and download, append and call anchor.click(), then defer
URL.revokeObjectURL(url) (for example via setTimeout or a short delay/onfocus
handler) and remove the anchor afterwards so the browser has time to start the
download; reference variables/functions: url, anchor, nowSeconds(), format.
- Around line 58-59: Replace the raw relation count with the number of
exportable rows: import toExportRows from ../../lib/memory/graphExport, compute
exportableRows = relations ? toExportRows(relations).length : null, and pass
count={exportableRows} into the GraphExportPanel so the badge reflects the
actual rows serializeGraph() will produce (handle null/undefined relations as
before).
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 162f7226-6bf1-48f1-aa87-be65e34b6559

📥 Commits

Reviewing files that changed from the base of the PR and between f895013 and 73ae7c0.

📒 Files selected for processing (23)
  • app/src/components/intelligence/GraphExportPanel.test.tsx
  • app/src/components/intelligence/GraphExportPanel.tsx
  • app/src/components/intelligence/GraphExportTab.test.tsx
  • app/src/components/intelligence/GraphExportTab.tsx
  • app/src/lib/i18n/chunks/ar-1.ts
  • app/src/lib/i18n/chunks/bn-1.ts
  • app/src/lib/i18n/chunks/de-1.ts
  • app/src/lib/i18n/chunks/en-1.ts
  • app/src/lib/i18n/chunks/es-1.ts
  • app/src/lib/i18n/chunks/fr-1.ts
  • app/src/lib/i18n/chunks/hi-1.ts
  • app/src/lib/i18n/chunks/id-1.ts
  • app/src/lib/i18n/chunks/it-1.ts
  • app/src/lib/i18n/chunks/ko-1.ts
  • app/src/lib/i18n/chunks/pt-1.ts
  • app/src/lib/i18n/chunks/ru-1.ts
  • app/src/lib/i18n/chunks/zh-CN-1.ts
  • app/src/lib/i18n/en.ts
  • app/src/lib/memory/graphExport.test.ts
  • app/src/lib/memory/graphExport.ts
  • app/src/pages/Intelligence.tsx
  • app/src/services/api/graphExportApi.test.ts
  • app/src/services/api/graphExportApi.ts

Comment thread app/src/components/intelligence/GraphExportTab.tsx Outdated
Comment thread app/src/components/intelligence/GraphExportTab.tsx Outdated
@sanil-23 sanil-23 self-assigned this May 29, 2026
aashir-athar added a commit to aashir-athar/openhuman that referenced this pull request May 29, 2026
…count

Address CodeRabbit review on tinyhumansai#2967:
- Defer URL.revokeObjectURL to a macrotask so the browser has started reading
  the Blob before it is freed (synchronous revoke can cancel the download).
- Show the EXPORTABLE row count (toExportRows drops malformed relations), not
  the raw relations.length, so the "N facts ready to export" label is accurate.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
coderabbitai[bot]
coderabbitai Bot previously approved these changes May 29, 2026
aashir-athar added a commit to aashir-athar/openhuman that referenced this pull request May 30, 2026
…count

Address CodeRabbit review on tinyhumansai#2967:
- Defer URL.revokeObjectURL to a macrotask so the browser has started reading
  the Blob before it is freed (synchronous revoke can cancel the download).
- Show the EXPORTABLE row count (toExportRows drops malformed relations), not
  the raw relations.length, so the "N facts ready to export" label is accurate.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
aashir-athar and others added 2 commits May 30, 2026 18:07
A new read-only "Export" tab for data portability: download the entire memory
knowledge graph as JSON or CSV — a different KIND of feature from the analytics
lenses, giving the user ownership of their data.

- Pure deterministic serializers (lib/memory/graphExport.ts): toJsonExport and
  toCsvExport over a stable {subject,predicate,object,namespace,evidenceCount,
  updatedAt} projection (malformed rows dropped). CSV follows RFC 4180 — fields
  containing comma/quote/CR/LF are quoted and embedded quotes doubled, with CRLF
  row terminators — so entity names with commas/quotes/newlines round-trip.
- Zero new core surface: reuses ONLY memoryGraphQuery. Read-only — the download
  (Blob + anchor) happens in the container's click handler, never during render.
- Container/presentational split; the container guards the load with a request
  token; the pure panel renders the count + a JSON/CSV format toggle + download
  button. i18n across all 13 locales.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…count

Address CodeRabbit review on tinyhumansai#2967:
- Defer URL.revokeObjectURL to a macrotask so the browser has started reading
  the Blob before it is freed (synchronous revoke can cancel the download).
- Show the EXPORTABLE row count (toExportRows drops malformed relations), not
  the raw relations.length, so the "N facts ready to export" label is accurate.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature Net-new user-facing capability or product behavior. memory Memory store, memory tree, recall, summarization, and embeddings in src/openhuman/memory/. working A PR that is being worked on by the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants