Adds vector-based semantic search across all chat sessions using Qdrant.
When a ChatTurn finishes, its content is chunked, embedded, and upserted
to a Qdrant collection. A search API and UI components enable searching
at user, project, and session scope.
Phase 1 — Configuration & Dependencies
- Add port/apiKey to GadgetCodeConfig.qdrant type
- Uncomment and update qdrant section in YAML config example
- Add qdrant config passthrough in env.ts
- Add @qdrant/js-client-rest dependency
Phase 2 — AI Embedding API (@gadget/ai)
- Add IAiEmbeddingResponse interface and abstract embeddings() to AiApi
- Implement embeddings() in OllamaAiApi (client.embeddings)
- Implement embeddings() in OpenAiApi (client.embeddings.create)
- Export IAiEmbeddingResponse from package index
Phase 3 — Backend Vector Store Service
- Create VectorStoreService (ingestTurn, search, removeTurnPoints)
- Hook fire-and-forget ingest after turn.save() in drone-session
- Register VectorStoreService in service startup/shutdown
Phase 4 — Backend Search API
- Create POST /api/v1/search controller with userId enforcement
- Batch-hydrate results from MongoDB (user, project, session, turn)
- Register search route in v1 API router
Phase 5 — Frontend Search Components
- SearchInput: debounced input with lucide-react icons
- ChatSearchResults: modal with score badges, metadata, loading states
- DroneSelectionModal: drone picker for sessions without a drone
- Add searchApi and ISearchResult to API client
- Add search to Home (global), ProjectManager (project), ChatSessionView (session)
- Add id=turn-{turnId} to ChatTurn for scroll targeting
- Scroll-to-turn from search result selection and router state
- Show DroneSelectionModal when no drone available
- Add Select Drone button in ChatSessionView sidebar
146 lines
7.1 KiB
YAML
146 lines
7.1 KiB
YAML
# ============================================================================
|
|
# Gadget Code Platform — Example Configuration
|
|
# ============================================================================
|
|
# Install this file to one of:
|
|
# ~/.config/gadget/gadget-code.yaml (user-level, takes precedence)
|
|
# /etc/gadget/gadget-code.yaml (system-level)
|
|
#
|
|
# Secrets MUST be stored in environment variables, NOT in this file.
|
|
# Use ${VAR_NAME} syntax to reference environment variables.
|
|
# ============================================================================
|
|
|
|
# Timezone for the server (used by dayjs and logging)
|
|
timezone: "America/New_York"
|
|
|
|
# ── Site Information ────────────────────────────────────────────────────────
|
|
# These values are exposed to the frontend and used in page titles, emails, etc.
|
|
site:
|
|
company: "Your Company"
|
|
companyShort: "YourCo"
|
|
name: "Gadget Code"
|
|
shortName: "Gadget"
|
|
slogan: "Self-hosted Agentic Engineering Platform"
|
|
description: "A self-hosted agentic development environment."
|
|
domain: "code.example.com" # Primary domain (no port)
|
|
domainKey: "code" # Short key used in cookie names, etc.
|
|
host: "code.example.com:3443" # Full host:port for URL generation
|
|
|
|
# ── Authentication (REQUIRED) ───────────────────────────────────────────────
|
|
# These values are MANDATORY. The server will refuse to start without them.
|
|
# Store them in environment variables — never commit secrets to this file.
|
|
auth:
|
|
jwtSecret: "${DTP_JWT_SECRET}" # JSON Web Token signing key
|
|
passwordSalt: "${DTP_USER_PASSWORD_SALT}" # Per-instance password hashing salt
|
|
|
|
# ── Session Configuration (REQUIRED) ─────────────────────────────────────────
|
|
# Express session stored in Redis via connect-redis.
|
|
session:
|
|
secret: "${DTP_SESSION_SECRET}" # Session signing key
|
|
trustProxy: true # Set true if behind a reverse proxy
|
|
cookie:
|
|
secure: true # Set true for HTTPS (required for SameSite=strict)
|
|
sameSite: "strict" # strict | lax | none
|
|
|
|
# ── Google Custom Search Engine (REQUIRED) ──────────────────────────────────
|
|
# Used by the drone's search_google tool for web search capabilities.
|
|
google:
|
|
cse:
|
|
apiKey: "${GOOGLE_CSE_API_KEY}" # Google API key with CSE enabled
|
|
engineId: "${GOOGLE_CSE_ENGINE_ID}" # Your custom search engine ID
|
|
|
|
# ── MongoDB Configuration ───────────────────────────────────────────────────
|
|
# The platform stores projects, chat sessions, users, providers, and drones here.
|
|
mongodb:
|
|
host: "localhost:27017" # MongoDB host:port
|
|
database: "gadget-code" # Database name
|
|
|
|
# ── Redis Configuration ─────────────────────────────────────────────────────
|
|
# Used for Express session storage (connect-redis) and caching.
|
|
redis:
|
|
host: "localhost"
|
|
port: 6379
|
|
password: "${REDIS_PASSWORD}" # Omit if Redis has no auth
|
|
keyPrefix: "gcode:" # Prefix for all keys in this instance
|
|
lazyConnect: false # Connect immediately on startup
|
|
|
|
# ── HTTPS Configuration ─────────────────────────────────────────────────────
|
|
# The platform server runs HTTPS directly. Place your cert and key on disk.
|
|
https:
|
|
enabled: true
|
|
address: "0.0.0.0" # Bind address (0.0.0.0 for all interfaces)
|
|
port: 3443 # Default HTTPS port
|
|
backlog: 128 # TCP backlog
|
|
keyFile: "/etc/ssl/gadget-code/key.pem" # Private key
|
|
crtFile: "/etc/ssl/gadget-code/cert.pem" # Certificate (full chain)
|
|
uploadPath: "/tmp/gadget-code" # Temp directory for file uploads
|
|
|
|
# ── Socket.IO Configuration ─────────────────────────────────────────────────
|
|
# Real-time communication between IDE, platform, and drones.
|
|
socket:
|
|
maxHttpBufferSize: 10485760 # 10 MB — max message size
|
|
|
|
# ── Logging Configuration ───────────────────────────────────────────────────
|
|
# Logs follow XDG Base Directory spec by default.
|
|
logging:
|
|
console:
|
|
enabled: true # Print to stdout/stderr
|
|
file:
|
|
enabled: true
|
|
path: "~/.local/state/gadget-code/logs" # Supports ~ expansion
|
|
name: "gadget-code"
|
|
maxWritesPerFile: 10000 # Rotate after this many writes
|
|
maxFiles: 10 # Keep this many rotated files
|
|
https:
|
|
enabled: true # HTTP access log (morgan format)
|
|
name: "gadget-code.https.log"
|
|
path: "~/.local/state/gadget-code/logs"
|
|
format: "combined" # morgan log format name
|
|
levels:
|
|
debug: true # Set false in production for less noise
|
|
info: true
|
|
warn: true
|
|
|
|
# ── Email Configuration (OPTIONAL) ──────────────────────────────────────────
|
|
# Enable for contact form submissions, password resets, and notifications.
|
|
email:
|
|
enabled: false
|
|
smtp:
|
|
host: "smtp.example.com"
|
|
port: 587
|
|
secure: false # true for port 465
|
|
from: "Gadget Code <noreply@example.com>"
|
|
user: "smtp-user"
|
|
password: "${SMTP_PASSWORD}"
|
|
pool:
|
|
enabled: true
|
|
maxConnections: 5
|
|
maxMessages: 100
|
|
contact:
|
|
to: "Support <support@example.com>"
|
|
|
|
# ── MinIO / S3 Configuration (OPTIONAL) ─────────────────────────────────────
|
|
# Object storage for uploaded files, images, videos, and audio.
|
|
minio:
|
|
endpoint: "localhost"
|
|
port: 9000
|
|
useSsl: false
|
|
accessKey: "minio-access-key"
|
|
secretKey: "${MINIO_SECRET_KEY}"
|
|
buckets:
|
|
uploads: "gadget-uploads"
|
|
images: "gadget-images"
|
|
videos: "gadget-videos"
|
|
audios: "gadget-audios"
|
|
|
|
# ── Qdrant Vector Database ──────────────────────────────────────────────────────
|
|
# Used for semantic search over chat history and conversation context.
|
|
#
|
|
qdrant:
|
|
host: "localhost"
|
|
port: 6333
|
|
apiKey: "${QDRANT_API_KEY}"
|
|
collection: "gadget-chat-embeddings"
|
|
providerId: "${QDRANT_PROVIDER_ID}" # AiProvider._id from the database
|
|
embeddingModel: "nomic-embed-text" # model name on the provider
|
|
vectorSize: 768 # must match the embedding model output
|