feat: Step 10 - Node Editor & AI-Powered Linking

Implemented the node editor page and AI-powered link suggestions:

1. Node Editor Page (/editor/[id]):
   - Form with title and body fields using Mantine
   - Pre-fill support from query params (for chat redirects)
   - "Find Related" button to discover similar nodes
   - "Publish Node" button to save to ATproto + SurrealDB
   - Display of suggested links with similarity scores
   - Mantine notifications for success/error feedback

2. Suggest Links API (/api/suggest-links):
   - Authenticates using SurrealDB JWT cookie
   - Generates embedding for draft text using Google AI
   - Performs vector similarity search using SurrealDB
   - Returns top 5 most similar nodes with cosine scores
   - Enforces row-level security (users only see their nodes)

3. Magnitude Tests:
   - Editor page rendering
   - Pre-filled form from query params
   - Publishing new nodes
   - Form validation

The editor integrates with the existing /api/nodes write-through
cache from Step 6, completing the node creation workflow.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-09 02:05:32 +00:00
parent af00f29bd4
commit 013575d6d5
3 changed files with 304 additions and 0 deletions

View File

@@ -0,0 +1,43 @@
import { test } from 'magnitude-test';
test('Editor page renders correctly', async (agent) => {
await agent.act('Navigate to /editor/new');
await agent.check('The text "Create New Node" is visible on the screen');
await agent.check('A text input field labeled "Title" is visible');
await agent.check('A textarea labeled "Body" is visible');
await agent.check('A button labeled "Find Related" is visible');
await agent.check('A button labeled "Publish Node" is visible');
});
test('[Happy Path] User can navigate to editor from chat', async (agent) => {
// Simulate pre-filled form from chat redirect
await agent.act('Navigate to /editor/new?title=My%20Idea&body=This%20is%20my%20thought');
await agent.check('The "Title" input contains "My Idea"');
await agent.check('The "Body" textarea contains "This is my thought"');
});
test('[Happy Path] User can fill out and publish a new node', async (agent) => {
// Navigate to the editor
await agent.act('Navigate to /editor/new');
// Fill out the form
await agent.act('Type "My First Published Node" into the "Title" input');
await agent.act('Type "This is the body of my first node. It contains interesting thoughts about technology and innovation." into the "Body" textarea');
// Click Publish
await agent.act('Click the "Publish Node" button');
// Check: User is redirected to chat (galaxy not implemented yet)
await agent.check('The page URL contains "/chat"');
});
test('[Unhappy Path] Publishing requires both title and body', async (agent) => {
await agent.act('Navigate to /editor/new');
// Try to publish without filling in the form
await agent.act('Click the "Publish Node" button');
// The form should prevent submission (Mantine form validation)
// The URL should still be /editor/new
await agent.check('The page URL contains "/editor/new"');
});