Ships accumulated WIP that was sitting uncommitted: - New (home) dashboard route pages: overview, code, data/tables, hosting, infrastructure, services, domains, integrations, agents, analytics, api, automations, billing, logs, market, marketing(+seo/social), product, security, storage, users, settings(app/auth). - dashboard-sidebar, project-icon-rail, chat-panel updates; mcp + anatomy route changes; package.json/lock dependency bumps. - Coolify log tooling (scripts/fetch-app-logs.mjs + fetch-app-logs-ssh.mjs) and ai-new-thread.md "Fetching Production Logs" section. Excludes throwaway debug scripts and telemetry audit dumps (the latter contain live credentials and must not be committed).
261 lines
16 KiB
Markdown
261 lines
16 KiB
Markdown
# VibnCode / Master-AI Context Injector
|
|
|
|
This file serves as a high-density, comprehensive bootstrap guide for any AI Coding Agent starting a new thread in this workspace.
|
|
|
|
---
|
|
|
|
## 1. System Architecture at a Glance
|
|
|
|
`VibnCode` (formerly TalkCody) is a **Cloud-Powered Agent Desktop IDE**. It functions as a high-fidelity window into cloud-hosted project workspaces, routing file modifications, terminal tasks, and AI session runs to a sandboxed Docker/Coolify VM backend.
|
|
|
|
```mermaid
|
|
graph TD
|
|
subgraph Client [Desktop client - vibn-code]
|
|
UI[React 19 / Monaco Editor UI]
|
|
State[Zustand Stores / SQLite Cache]
|
|
Tauri[Tauri v2 App Wrapper]
|
|
end
|
|
|
|
subgraph CloudRunner [Cloud Workspace - vibn-agent-runner]
|
|
Runner[Agent Session Runner Engine]
|
|
Workspace[Sandboxed Project Dir: /workspaces]
|
|
end
|
|
|
|
subgraph Infrastructure [Vibnai Platform]
|
|
DB[(PostgreSQL Database)]
|
|
WebAPI[Next.js API Server: vibn-frontend]
|
|
Gitea[(Gitea Git Server)]
|
|
Coolify[Coolify Server Hosting]
|
|
end
|
|
|
|
UI <-->|Event Streams & Cloud FS| WebAPI
|
|
WebAPI -->|Route Exec Request| Runner
|
|
Runner <-->|Code Edits & Shell Runs| Workspace
|
|
Runner <-->|Push/Pull/Clone Code| Gitea
|
|
Runner -->|Manage & Deploy Apps| Coolify
|
|
```
|
|
|
|
---
|
|
|
|
## 2. Directory Structure & Individual Git Repositories
|
|
|
|
> **`master-ai` is a LOCAL development workspace on Mark's Mac. It does not exist in production and is never accessed by any running cloud service.** Production runs entirely from the individual Gitea repositories → Coolify builds → running containers on `34.19.250.135`. Once a change is pushed to the matching Gitea remote, `master-ai` is completely out of the picture.
|
|
|
|
The local `master-ai` directory houses folders that each map to an **independent Gitea repository**. The `master-ai` git repo itself is just a convenience — a single place to commit and track changes across all sub-projects before pushing each one to its own Gitea remote.
|
|
|
|
DO NOT treat `master-ai` as a single monorepo on Gitea — it is not deployed as one. You must push changes inside specific directories to their matching Gitea remote targets.
|
|
|
|
```
|
|
/Users/markhenderson/master-ai/ <-- Local Parent Directory
|
|
├── vibn-code/ <-- Nested Git Repository (Submodule)
|
|
│ Remote 'origin' -> https://git.vibnai.com/mark/vibn-code.git (main)
|
|
├── vibn-agent-runner/ <-- Subfolder of master-ai. Pushes via:
|
|
│ Remote 'coolify_agent_gitea' -> https://git.vibnai.com/mark/vibn-agent-runner.git
|
|
├── vibn-frontend/ <-- Subfolder of master-ai. Pushes via:
|
|
│ Remote 'coolify_gitea' -> https://git.vibnai.com/mark/vibn-frontend.git
|
|
├── vibn-api/ <-- Subfolder of master-ai. Pushes via:
|
|
│ Remote 'coolify_api_gitea' -> https://git.vibnai.com/mark/vibn-api.git
|
|
└── vibn-telemetry-service/ <-- Subfolder of master-ai (Training Data Microservice). Pushes via:
|
|
Remote 'coolify_telemetry_gitea' -> https://git.vibnai.com/mark/vibn-telemetry-service.git
|
|
```
|
|
|
|
### Git Remotes Reference (local Mac remotes — these exist only on Mark's machine):
|
|
|
|
These are git remotes configured in the local `master-ai` repo. They are the **one-way bridge** between local development and production. Production Coolify services pull directly from the Gitea URLs; they have no knowledge of `master-ai`.
|
|
|
|
| Remote | Gitea URL | What it deploys |
|
|
|---|---|---|
|
|
| `coolify_gitea` | `https://git.vibnai.com/mark/vibn-frontend.git` | vibn-frontend (Next.js platform) |
|
|
| `coolify_agent_gitea` | `https://git.vibnai.com/mark/vibn-agent-runner.git` | vibn-agent-runner |
|
|
| `coolify_api_gitea` | `https://git.vibnai.com/mark/vibn-api.git` | vibn-api |
|
|
| `coolify_telemetry_gitea` | `https://git.vibnai.com/mark/vibn-telemetry-service.git` | vibn-telemetry-service |
|
|
| `gitea` | `https://git.vibnai.com/mark/master-ai.git` | *(share-only — coworker local setup; **builds do NOT use this**)* |
|
|
| `origin` | `https://github.com/MawkOne/master-ai.git` | *(GitHub mirror only — not used by Coolify)* |
|
|
|
|
**The full deploy lifecycle:**
|
|
```
|
|
Local Mac (master-ai) → git push <remote> HEAD:main → Gitea repo → Coolify build → Production
|
|
↑ ↑
|
|
master-ai ends here Production begins here
|
|
```
|
|
|
|
1. Make changes in `master-ai/vibn-frontend/` (or whichever subfolder).
|
|
2. `git commit` in `master-ai`.
|
|
3. `git push coolify_gitea HEAD:main` (or relevant remote) — **this is the complete hand-off**.
|
|
4. Coolify detects the push, builds a Docker image from the Gitea repo, and deploys it.
|
|
5. `master-ai` is no longer involved. Production runs entirely from the Gitea repo + Coolify.
|
|
|
|
`vibn-code` is a nested submodule with its own `.git` — commit & push it via its own `origin`.
|
|
Secret `.env*` files at the repo root are gitignored — never commit them.
|
|
|
|
**⚠️ NEVER use `git subtree push` for these remotes.** Coolify is configured with `vibn-frontend` as its **base directory**, so it expects the full `master-ai` repo structure at the Gitea root and resolves the Dockerfile at `vibn-frontend/Dockerfile`. A subtree push flattens the repo to just the subfolder contents, making `vibn-frontend/` disappear and breaking the build with `open Dockerfile: no such file or directory`. Always use:
|
|
```bash
|
|
git push <remote> HEAD:main # normal
|
|
git push <remote> HEAD:main --force # if remote has diverged
|
|
```
|
|
|
|
### Deploying the Telemetry Service manually via Coolify UI:
|
|
Because Coolify's API strictly blocks the programmatic creation of GitHub/Gitea Apps, the Telemetry service must be linked manually once:
|
|
1. Open [Coolify Dashboard -> vibn-infrastructure -> production](https://coolify.vibnai.com/project/f4owwggokksgw0ogo0844os0/environment/foskksoccksk0kc4g8sk88ok)
|
|
2. Click **+ Add -> Application -> Private Repository (with Gitea)**.
|
|
3. Select `vibn-telemetry-service` and branch `main`.
|
|
4. Set Build Pack to `Dockerfile` and Ports Exposes to `4000`.
|
|
5. Under Environment Variables, add `DATABASE_URL=postgresql://<user>:<password>@<host>/<database>`
|
|
6. Deploy it, then add `TELEMETRY_SERVICE_URL=http://<the-new-coolify-url>:4000` to the `vibn-frontend` environments.
|
|
|
|
---
|
|
|
|
## 3. Key Tech Stacks & Development Tools
|
|
|
|
### Runtimes & Package Managers (Local Mac)
|
|
* **Bun**: **NOT installed** on this local Mac's CLI path. Use **`pnpm`** (v10.33.2) or **`node`** (v24.1.0) instead.
|
|
* **Rust**: Fully configured. Built/managed via cargo.
|
|
|
|
### Sub-Project Configurations
|
|
|
|
#### A. `vibn-code` (The Desktop App)
|
|
* **Frontend**: React 19 + TypeScript + Zustand + Tailwind CSS v4 + Shadcn UI + Monaco Editor.
|
|
* **Backend**: Tauri v2 + Rust (split into `core` and `desktop` workspace members).
|
|
* **Startup Command**:
|
|
```bash
|
|
cd /Users/markhenderson/master-ai/vibn-code
|
|
pnpm dev:tauri # Compiles Rust backend, launches desktop shell, and starts Vite
|
|
```
|
|
*(To start React web preview only, run `pnpm dev`)*
|
|
|
|
#### B. `vibn-frontend` (The Next.js Web Dashboard & API Bridge)
|
|
* **Frontend/Backend**: Next.js + PostgreSQL + NextAuth.js.
|
|
* **Startup Command**:
|
|
```bash
|
|
cd /Users/markhenderson/master-ai/vibn-frontend
|
|
docker compose -f docker-compose.local-db.yml up -d # Start local Postgres
|
|
pnpm dev # Start Next.js
|
|
```
|
|
|
|
#### C. `vibn-api`
|
|
* **Stack**: Bun/TypeScript + Drizzle ORM + sqlite/libsql + Wrangler/Cloudflare.
|
|
|
|
---
|
|
|
|
## 4. The Cloud-Powered Bridge Architecture
|
|
|
|
VibnCode overrides local OS actions to communicate with your cloud containers (on GCP VM `34.19.250.135` via Coolify/Traefik):
|
|
|
|
1. **Virtual Filesystem (`src/services/cloud-fs-service.ts` & `repository-service.ts`)**:
|
|
Monaco & File Tree operations POST to Next.js `/api/mcp` with actions `"fs_tree"`, `"fs_read"`, and `"fs_write"`.
|
|
* `fs_tree` returns an ASCII tree parsed by `parseAsciiTreeToNodes` on the client into UI `FileNode` trees.
|
|
2. **Server-Delegated Run-Loop (`src/services/execution-service.ts`)**:
|
|
Instead of launching local task compilers, the client calls `POST /api/projects/:projectId/agent/sessions` and initiates a real-time `while (isRunning)` polling loop against PostgreSQL to pull output lines and stream them to the Monaco chat panel.
|
|
3. **SSO Authentication Loop (`vibncode://` Custom Scheme)**:
|
|
OAuth logins redirect from Gitea back to `vibncode://auth/callback?token=...`.
|
|
* **Important:** This scheme is registered in macOS via `vibn-code/src-tauri/Info.plist` (updated and verified).
|
|
* Relaunching/recompiling the app (`pnpm dev:tauri`) registers `vibncode://` with Launch Services, enabling local SSO redirects.
|
|
|
|
---
|
|
|
|
## 5. Development Guidelines & Safety Nets
|
|
|
|
1. **Rust Clippy Warnings are treated as Errors**:
|
|
The pre-commit hooks will fail commits if cargo clippy warnings exist.
|
|
* *Unused structs*: Annotate with `#[allow(dead_code)]`.
|
|
* *Nested matches/ifs*: Collapse nested `if` statements into outer `match` arms using pattern guards (e.g. `ContentPart::Text { text } if !text.trim().is_empty() => { ... }`).
|
|
2. **Commit Bypasses**:
|
|
If blocking cargo file locks (`Blocking waiting for file lock on build directory`) occur because the app is running, stage your changes and commit using `--no-verify` to bypass pre-commit compilation:
|
|
```bash
|
|
git commit -m "commit message" --no-verify
|
|
```
|
|
3. **Push to Individual remotes (the ONLY way changes reach production)**:
|
|
Commit in `master-ai`, then push the relevant subfolder's remote. Production never reads from `master-ai` directly — the push to Gitea is the complete hand-off.
|
|
```bash
|
|
git push coolify_gitea HEAD:main # deploy vibn-frontend
|
|
git push coolify_agent_gitea HEAD:main # deploy vibn-agent-runner
|
|
git push coolify_api_gitea HEAD:main # deploy vibn-api
|
|
git push coolify_telemetry_gitea HEAD:main # deploy vibn-telemetry-service
|
|
```
|
|
|
|
---
|
|
|
|
## 6. Where We Left Off (As of May 31, 2026)
|
|
|
|
**Read `VIBNCODE_THIN_CLIENT_CHANGES.md` first** — it is the live, prioritized change list with exact files,
|
|
steps, and acceptance criteria for the thin-client conversion, plus a STATUS section of what's done.
|
|
|
|
**Chat works end-to-end.** A desktop message → `POST /api/projects/:id/agent/sessions` → cloud runner executes
|
|
the Coder agent (Gemini) → output polled back into the Monaco chat. Recent fixes that got it there:
|
|
|
|
* **Local SQLite was wiping chats (fixed):** `database-service.ts` used `INSERT OR REPLACE INTO projects`, which
|
|
(via `ON DELETE CASCADE`) deleted the active conversation mid-run. Switched to UPSERT; made `task-service`
|
|
persistence non-blocking. The cloud is the source of truth; local SQLite is just a cache.
|
|
* **Empty `appPath` broke every run (fixed):** the desktop sent `appPath: ""`; the runner's `/agent/execute`
|
|
rejects falsy `appPath` with HTTP 400 and does nothing (no logs). Desktop now sends `appPath: "."`.
|
|
* **Agent tools `fetch failed` (fixed, pushed):** the runner's `buildContext()` hardcoded
|
|
`vibnApiUrl: 'http://localhost:3000'` and an empty `mcpToken`, so tool calls fetched a dead port. Now
|
|
`/agent/execute` reads `mcpToken` from the body and sets `ctx.vibnApiUrl` (from `VIBN_API_URL`) + `mcpToken`.
|
|
Pushed to `coolify_agent_gitea/main` — confirm the runner redeploy.
|
|
* **Single model:** desktop model picker restricted to the VibnAI model, relabeled "Gemini 3.5 Flash". The
|
|
runner's real model is set by `GEMINI_MODEL` env (currently `gemini-3.1-pro-preview`); the desktop label is
|
|
cosmetic until model-passthrough is wired (CHANGE 4.1 in the change doc).
|
|
|
|
**Known open items (in the change doc):** the desktop still has a hardcoded `vibn_sk_` API key to remove;
|
|
`/agent/sessions/:id/stop` returns 401 to the desktop (uses browser-session auth, not the workspace key); runner
|
|
early-failures are silently swallowed (failure PATCHes omit the `x-agent-runner-secret` header).
|
|
|
|
**Earlier (still true):** `vibncode://` deep link scheme is registered in `src-tauri/Info.plist`; Rust clippy is
|
|
treated as errors on commit.
|
|
|
|
---
|
|
|
|
## 7. Fetching Production Logs (Coolify apps)
|
|
|
|
The Coolify dashboard (`https://coolify.vibnai.com/...`) is login-walled, so to read an app's logs
|
|
programmatically use one of the two paths below. Both read credentials from `vibn-frontend/.env.local`
|
|
(`COOLIFY_URL`, `COOLIFY_API_TOKEN`, and `COOLIFY_SSH_HOST` / `COOLIFY_SSH_PORT` / `COOLIFY_SSH_USER` /
|
|
`COOLIFY_SSH_PRIVATE_KEY_B64`).
|
|
|
|
**The `<appUuid>` is the last path segment of the Coolify app URL:**
|
|
`.../application/y4cscsc8s08c8808go0448s0` -> appUuid = `y4cscsc8s08c8808go0448s0`.
|
|
|
|
| App | appUuid | Build pack | Notes |
|
|
|---|---|---|---|
|
|
| `vibn-frontend` | `y4cscsc8s08c8808go0448s0` | dockerfile | Next.js, port 3000, fqdn vibnai.com |
|
|
| `vibn-telemetry` | `hou4vy5mtyg5mrx3w4nl2lxv` | dockerfile | port 4000; usage data lives in its **DB**, not stdout |
|
|
|
|
### Method A - Coolify REST API (simplest)
|
|
`GET {COOLIFY_URL}/api/v1/applications/{uuid}/logs?lines=N` with `Authorization: Bearer {COOLIFY_API_TOKEN}`.
|
|
Returns `{ logs: "..." }`. Works for dockerfile / nixpacks / static apps; returns **empty for `dockercompose`**
|
|
(Coolify can't pick which service to tail). Helper script:
|
|
```bash
|
|
cd vibn-frontend
|
|
node scripts/fetch-app-logs.mjs <appUuid> [lines] # reads .env.local itself
|
|
```
|
|
|
|
### Method B - SSH + `docker logs` (full history, timestamps, date filter)
|
|
Use when the REST endpoint returns little/nothing (compose apps, or quiet services). Connects to the host with
|
|
the `ssh2` lib and runs `docker logs` against the app's container(s). Coolify names containers
|
|
`{appUuid}-{hash}`; a zero-downtime deploy briefly leaves TWO containers (old draining + new). Helper script:
|
|
```bash
|
|
cd vibn-frontend
|
|
# everything since the start of a UTC day (note: logs are UTC):
|
|
node --env-file=.env.local scripts/fetch-app-logs-ssh.mjs <appUuid> 2026-06-12
|
|
# last 500 lines, no date filter:
|
|
node --env-file=.env.local scripts/fetch-app-logs-ssh.mjs <appUuid> "" 500
|
|
# target a specific container during a rollout (substring match):
|
|
node --env-file=.env.local scripts/fetch-app-logs-ssh.mjs <appUuid>-003647723804 2026-06-12
|
|
```
|
|
Under the hood (reusable one-off): `runOnCoolifyHost()` in `lib/coolify-ssh.ts`, or for the compose-aware
|
|
unified fetcher, `getApplicationRuntimeLogs()` in `lib/coolify-logs.ts` (API first, SSH `docker logs` fallback).
|
|
List an app's containers: `docker ps -a --filter name=<appUuid> --format '{{.Names}}\t{{.Status}}'`.
|
|
|
|
### Important caveat - container logs are NOT "usage logs"
|
|
Both the Next.js frontend (production server) and the telemetry service only emit **startup lines + explicit
|
|
`console.error`** to stdout - they do NOT log per-request activity. So `docker logs` is the right tool for
|
|
**deploy health and crashes/errors**, but for actual product **usage** you must query the data store:
|
|
- **Telemetry / usage** is written to Postgres by `vibn-telemetry-service` (its own `DATABASE_URL`). The existing
|
|
extractors (`vibn-frontend/scripts/extract-live-telemetry.ts`, `extract-ui-telemetry.ts`) pull telemetry by
|
|
querying `fs_chat_threads` / `fs_chat_messages` via `DATABASE_URL` - copy their pattern for date-ranged usage.
|
|
- **Runtime errors** at scale are captured by **Sentry** (auto-provisioned per project), not container stdout.
|
|
|
|
### Verifying a deploy landed
|
|
`GET /api/v1/applications/{uuid}` returns `status` (`running:healthy` when good). On a fresh deploy the new
|
|
container shows `Up About a minute (healthy)` and the previous one disappears once draining completes.
|