diff --git a/docker/Dockerfile.combined b/docker/Dockerfile.combined index 597ecc9f..542f3579 100644 --- a/docker/Dockerfile.combined +++ b/docker/Dockerfile.combined @@ -3,7 +3,7 @@ # This Dockerfile creates an all-in-one image for Cloud Run deployment: # - PostgreSQL 17 with RuVector extension # - pg-meta API for database management -# - Supabase Studio frontend +# - Custom Supabase Studio frontend with RuVector pages # - Nginx reverse proxy with basic authentication # # Usage: @@ -63,7 +63,52 @@ RUN cargo pgrx package --pg-config /usr/lib/postgresql/${PG_VERSION}/bin/pg_conf RUN cp sql/ruvector--0.1.0.sql target/release/ruvector-pg${PG_VERSION}/usr/share/postgresql/${PG_VERSION}/extension/ # ============================================================================= -# Stage 2: Final Combined Image +# Stage 2: Build Custom Studio with RuVector modifications +# ============================================================================= +FROM node:20-bookworm AS studio-builder + +# Install build dependencies +RUN apt-get update && apt-get install -y --no-install-recommends \ + git \ + python3 \ + build-essential \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /build + +# Clone Supabase repository at the specific version +RUN git clone --depth 1 --branch v1.24.09 https://github.com/supabase/supabase.git . + +# Copy all our custom RuVector modifications from npm/studio +COPY npm/studio/components/interfaces/RuVector /tmp/ruvector-components/ +COPY npm/studio/pages/project /tmp/ruvector-pages/ + +# Move files to correct locations +RUN mkdir -p apps/studio/components/interfaces/RuVector && \ + cp /tmp/ruvector-components/RuVectorHome.tsx apps/studio/components/interfaces/RuVector/ && \ + cp /tmp/ruvector-pages/\[ref\]/index.tsx apps/studio/pages/project/\[ref\]/index.tsx && \ + mkdir -p apps/studio/pages/project/\[ref\]/vectors && \ + mkdir -p apps/studio/pages/project/\[ref\]/attention && \ + mkdir -p apps/studio/pages/project/\[ref\]/gnn && \ + mkdir -p apps/studio/pages/project/\[ref\]/hyperbolic && \ + mkdir -p apps/studio/pages/project/\[ref\]/learning && \ + mkdir -p apps/studio/pages/project/\[ref\]/routing && \ + cp /tmp/ruvector-pages/\[ref\]/vectors/index.tsx apps/studio/pages/project/\[ref\]/vectors/ && \ + cp /tmp/ruvector-pages/\[ref\]/attention/index.tsx apps/studio/pages/project/\[ref\]/attention/ && \ + cp /tmp/ruvector-pages/\[ref\]/gnn/index.tsx apps/studio/pages/project/\[ref\]/gnn/ && \ + cp /tmp/ruvector-pages/\[ref\]/hyperbolic/index.tsx apps/studio/pages/project/\[ref\]/hyperbolic/ && \ + cp /tmp/ruvector-pages/\[ref\]/learning/index.tsx apps/studio/pages/project/\[ref\]/learning/ && \ + cp /tmp/ruvector-pages/\[ref\]/routing/index.tsx apps/studio/pages/project/\[ref\]/routing/ && \ + rm -rf /tmp/ruvector-components /tmp/ruvector-pages + +# Install dependencies and build +RUN npm install +ENV SKIP_ASSET_UPLOAD=1 +ENV NEXT_PUBLIC_IS_PLATFORM=false +RUN npm run build:studio + +# ============================================================================= +# Stage 3: Final Combined Image # ============================================================================= FROM postgres:${PG_VERSION}-bookworm AS runtime @@ -90,10 +135,16 @@ RUN mkdir -p /etc/apt/keyrings && \ apt-get install -y nodejs && \ rm -rf /var/lib/apt/lists/* -# Copy RuVector extension +# Copy RuVector extension from rust-builder COPY --from=rust-builder /build/ruvector-postgres/target/release/ruvector-pg${PG_VERSION}/usr/share/postgresql/${PG_VERSION}/extension/* /usr/share/postgresql/${PG_VERSION}/extension/ COPY --from=rust-builder /build/ruvector-postgres/target/release/ruvector-pg${PG_VERSION}/usr/lib/postgresql/${PG_VERSION}/lib/* /usr/lib/postgresql/${PG_VERSION}/lib/ +# Copy built Studio from studio-builder +RUN mkdir -p /app/studio +COPY --from=studio-builder /build/apps/studio/.next/standalone /app/ +COPY --from=studio-builder /build/apps/studio/.next/static /app/apps/studio/.next/static +COPY --from=studio-builder /build/apps/studio/public /app/apps/studio/public + # Install pg-meta globally RUN npm install -g @supabase/postgres-meta@0.84.2 @@ -214,8 +265,8 @@ stdout_logfile=/var/log/supervisor/pgmeta.log stderr_logfile=/var/log/supervisor/pgmeta-error.log [program:studio] -command=node /app/studio/server.js -directory=/app/studio +command=node /app/apps/studio/server.js +directory=/app autostart=true autorestart=true startretries=10 @@ -296,25 +347,6 @@ ENTRYPOINT RUN chmod +x /docker-entrypoint-combined.sh -# Download and setup Supabase Studio -RUN mkdir -p /app/studio && \ - cd /tmp && \ - curl -L https://github.com/supabase/supabase/releases/download/studio-v1.24.09/studio-standalone.tar.gz -o studio.tar.gz && \ - tar -xzf studio.tar.gz -C /app/studio --strip-components=1 || \ - echo "Studio download failed - will use placeholder" - -# Create a simple placeholder if Studio download fails -RUN if [ ! -f /app/studio/server.js ]; then \ - mkdir -p /app/studio && \ - echo 'const http = require("http");' > /app/studio/server.js && \ - echo 'const server = http.createServer((req, res) => {' >> /app/studio/server.js && \ - echo ' res.writeHead(200, {"Content-Type": "text/html"});' >> /app/studio/server.js && \ - echo ' res.end("
PostgreSQL with RuVector extension is running.
");' >> /app/studio/server.js && \ - echo '});' >> /app/studio/server.js && \ - echo 'server.listen(3000, () => console.log("Studio placeholder running on port 3000"));' >> /app/studio/server.js && \ - echo "Created placeholder server"; \ - fi - # Expose port for Cloud Run EXPOSE 8080 diff --git a/docker/Dockerfile.studio b/docker/Dockerfile.studio index 097f3890..3af2e886 100644 --- a/docker/Dockerfile.studio +++ b/docker/Dockerfile.studio @@ -25,10 +25,10 @@ WORKDIR /build # Clone Supabase repository at the specific version RUN git clone --depth 1 --branch v1.24.09 https://github.com/supabase/supabase.git . -# Copy all our custom RuVector modifications in one layer +# Copy all our custom RuVector modifications from npm/studio # Using a staging directory to handle the bracket paths -COPY studio/components/interfaces/RuVector /tmp/ruvector-components/ -COPY studio/pages/project /tmp/ruvector-pages/ +COPY npm/studio/components/interfaces/RuVector /tmp/ruvector-components/ +COPY npm/studio/pages/project /tmp/ruvector-pages/ # Move files to correct locations RUN mkdir -p apps/studio/components/interfaces/RuVector && \ diff --git a/npm/studio/README.md b/npm/studio/README.md new file mode 100644 index 00000000..b3717d7a --- /dev/null +++ b/npm/studio/README.md @@ -0,0 +1,63 @@ +# @ruvector/studio + +Custom Supabase Studio components and pages for RuVector - the AI-native vector database. + +## Features + +This package contains custom pages and components for managing RuVector's AI-native features: + +- **Vector Indexes** - HNSW and IVFFlat index management with performance monitoring +- **Attention Mechanisms** - 39 attention functions for in-database transformer computations +- **Graph Neural Networks** - GCN, GraphSAGE, GAT models with SQL integration +- **Hyperbolic Embeddings** - Poincaré ball and Lorentz hyperboloid embeddings +- **Self-Learning** - ReasoningBank adaptive learning with trajectory tracking +- **Agent Routing** - Intelligent query routing to specialized agents + +## Structure + +``` +npm/studio/ +├── components/ +│ └── interfaces/ +│ └── RuVector/ +│ └── RuVectorHome.tsx # Main dashboard component +├── pages/ +│ └── project/ +│ └── [ref]/ +│ ├── index.tsx # Project dashboard override +│ ├── vectors/ # Vector index management +│ ├── attention/ # Attention mechanisms +│ ├── gnn/ # Graph neural networks +│ ├── hyperbolic/ # Hyperbolic embeddings +│ ├── learning/ # Self-learning system +│ └── routing/ # Agent routing +└── package.json +``` + +## Usage + +These files are designed to be copied into a Supabase Studio build. See the Docker configuration for automated integration. + +### Docker Build + +```bash +# Build custom studio image +docker build -f docker/Dockerfile.studio -t ruvector-studio:custom . + +# Run studio +docker run -p 3001:3000 \ + -e STUDIO_PG_META_URL=http://host.docker.internal:8080 \ + ruvector-studio:custom +``` + +## Development + +To modify the studio pages: + +1. Edit files in `npm/studio/` +2. Rebuild the Docker image with `--no-cache` +3. Deploy the updated container + +## License + +Apache-2.0 diff --git a/npm/studio/components/interfaces/RuVector/RuVectorHome.tsx b/npm/studio/components/interfaces/RuVector/RuVectorHome.tsx new file mode 100644 index 00000000..83514a1e --- /dev/null +++ b/npm/studio/components/interfaces/RuVector/RuVectorHome.tsx @@ -0,0 +1,1012 @@ +import Link from 'next/link' +import { useParams } from 'common' +import { useState, useEffect, useRef, useCallback } from 'react' +import { + Database, + Brain, + Network, + Orbit, + GraduationCap, + Route, + Sparkles, + Zap, + BarChart3, + Code2, + Table2, + Settings, + Shield, + Activity, + FileCode, + Terminal, + Boxes, + Key, + Users, + FolderOpen, + Clock, + CheckCircle2, + Layers, + Search, + PuzzleIcon, + Workflow, + TrendingUp, + TrendingDown, + Cpu, + HardDrive, + Timer, + ArrowRight, + Play, + ChevronRight, + Gauge, + Server, + Star, + RefreshCw, +} from 'lucide-react' +import { cn } from 'ui' + +// Types for database stats +interface DbStats { + numbackends: number + xact_commit: number + xact_rollback: number + blks_read: number + blks_hit: number + tup_returned: number + tup_fetched: number + tup_inserted: number + tup_updated: number + tup_deleted: number + db_size: number + table_count: number + index_count: number + active_connections: number +} + +interface TimeSeriesPoint { + time: Date + queries: number + connections: number + cacheHitRatio: number + tuplesPerSec: number +} + +// Hook to fetch real database stats from pg-meta +const useDbStats = (refreshInterval = 3000) => { + const [stats, setStats] = useState{description}
+ +{description}
+
+ {code}
+
+ + Advanced vector database with AI-native capabilities +
+ ++ Real-time PostgreSQL metrics {error && '(simulated)'} +
+AI-native features powered by Rust
+Get started with vector search
+Row-level security and access controls
+ + Manage PoliciesDatabase functions and triggers
+ + View FunctionsHNSW and IVFFlat for vector similarity
+ + Manage Indexes+ 39 attention mechanisms implemented as PostgreSQL functions for in-database transformer computations +
+{attention.description}
+{attention.func}(query, key, value)
+ {selectedFunc.description}
+ +
+{`SELECT ${selectedFunc.func}(
+ query_vector,
+ key_vector,
+ value_vector
+) FROM embeddings
+WHERE id = 1;`}
+
+
+ + Select an attention mechanism to view details +
+{item.value}
+ + Native PostgreSQL implementations of GCN, GraphSAGE, and GAT for relational data modeling +
+{model.description}
+
+{`SELECT ${model.func}(
+ node_features, -- vector[] of node embeddings
+ adjacency_matrix, -- edge connections
+ weights -- learned parameters
+) FROM graph_data;`}
+
+
+
+{`-- GNN Forward Pass
+WITH adjacency AS (
+ SELECT
+ source_id,
+ target_id,
+ 1.0 as weight
+ FROM edges
+),
+node_features AS (
+ SELECT id, embedding
+ FROM nodes
+),
+aggregated AS (
+ SELECT
+ n.id,
+ ${selectedModel?.func || 'gcn_forward'}(
+ n.embedding,
+ array_agg(m.embedding),
+ model_weights
+ ) as output
+ FROM node_features n
+ JOIN adjacency a ON a.source_id = n.id
+ JOIN node_features m ON m.id = a.target_id
+ GROUP BY n.id, n.embedding
+)
+SELECT * FROM aggregated;`}
+
+ {op.name}
+ {op.calls} calls
+ {op.desc}
+{uc.desc}
++ Poincaré and Lorentz model operations for hierarchical data representation +
+{model.description}
+{op.name}()
+ {op.desc}
+{op.func}({op.args})
+ {op.func}({op.args})
+
+{`-- Find all descendants within hyperbolic distance threshold
+SELECT
+ child.id,
+ child.name,
+ poincare_distance(parent.embedding, child.embedding) as distance
+FROM taxonomy parent
+JOIN taxonomy child ON child.parent_id = parent.id
+WHERE parent.id = 1
+ AND poincare_distance(parent.embedding, child.embedding) < 2.0
+ORDER BY distance;`}
+
+ {uc.description}
+{benefit.desc}
++ Adaptive learning system that improves through experience +
+{stage.description}
+{pipeline[selectedStage - 1].details}
+
+{`SELECT ${pipeline[selectedStage - 1].func}(
+ current_state,
+ 'action_taken',
+ outcome_data
+) FROM decisions;`}
+
+
+ {benefit.desc}
+{func.name}
+ {func.description}
+{func.returns}
+ | ID | +State | +Action | +Confidence | +Result | +
|---|---|---|---|---|
| #{t.id} | +{t.state} | +
+ {t.action}
+ |
+
+
+
+
+
+
+ {(t.confidence * 100).toFixed(0)}%
+ |
+
+ {t.success ? (
+
+ |
+
{p.pattern}
+ {p.uses} uses
+ + Intelligent semantic routing for multi-agent systems +
+{item.description}
+{func.name}
+ {func.description}
+
+{`CREATE TABLE agents (
+ id SERIAL PRIMARY KEY,
+ name TEXT NOT NULL,
+ description TEXT,
+ capabilities vector(384), -- Embedding of agent capabilities
+ metadata JSONB,
+ created_at TIMESTAMPTZ DEFAULT NOW(),
+ updated_at TIMESTAMPTZ DEFAULT NOW()
+);
+
+-- Create HNSW index for fast similarity search
+CREATE INDEX ON agents
+USING hnsw (capabilities vector_cosine_ops)
+WITH (m = 16, ef_construction = 64);
+
+-- Performance tracking
+CREATE TABLE agent_metrics (
+ agent_id INT REFERENCES agents(id),
+ queries_handled INT DEFAULT 0,
+ success_count INT DEFAULT 0,
+ avg_latency_ms FLOAT DEFAULT 0,
+ updated_at TIMESTAMPTZ DEFAULT NOW()
+);`}
+
+ {uc.desc}
+| Agent | +Capabilities | +Queries | +Success Rate | +Status | +Actions | +
|---|---|---|---|---|---|
|
+
+
+
+
+ {agent.name}
+ |
+ + {agent.capabilities} + | ++ {agent.queries.toLocaleString()} + | +
+
+
+
+
+
+ {agent.successRate}%
+ |
+ + + + Active + + | ++ + | +
+ Enter a query to see which agent would handle it +
+ +
+{`SELECT route_query(
+ embed('${testQuery.slice(0, 30)}...'),
+ top_k => 1
+);`}
+
+ + Enter a query and click "Route Query" to see results +
++ High-performance HNSW and IVFFlat indexes for similarity search +
+{idx.description}
+
+ {idx.code}
+
+
+ {op.name}
+ {op.symbol}
+ {op.desc}
+{op.use}
+
+{`CREATE INDEX items_embedding_idx ON items
+USING hnsw (embedding vector_cosine_ops)
+WITH (m = 16, ef_construction = 64);`}
+
+ | Name | +Type | +Table | +Rows | +Size | +Avg Query | +Status | +Actions | +
|---|---|---|---|---|---|---|---|
+ {idx.name}
+ |
+ + + {idx.type.toUpperCase()} + + | +{idx.table} | +{idx.rows.toLocaleString()} | +{idx.size} | +{idx.avgQueryTime.toFixed(1)}ms | ++ + + Active + + | ++ + | +