The tools have evolved. Have you?
https://g4dge7.com/
This commit addresses two interrelated issues causing drones to
de-register and users to be forcibly signed out:
## Heartbeat Timeout Fixes
1. Move heartbeat interval to a Web Worker (not subject to browser
tab throttling). Chrome throttles setInterval in background tabs
to ~1/min, which causes the 19s heartbeat to miss the drone's
timeout timer. The Web Worker fires reliably regardless of tab
visibility.
2. Add visibilitychange handler: when the tab becomes visible again,
send an immediate heartbeat to reset the drone's timer after any
throttling that may have occurred.
3. Fix onReleaseSessionLock to clear the heartbeat timer. Previously,
releasing the lock left the 60s timer running, causing a spurious
timeout and status emit after the lock was already released.
4. Increase drone heartbeat timeout from 60s to 120s. With the Web
Worker fix, heartbeats should be reliable, but doubling the timeout
provides a generous safety margin.
5. Add socket disconnect/reconnect handlers on the drone side. On
disconnect, clear the heartbeat timer. On reconnect, re-emit drone
status so the platform knows the drone is alive.
6. Configure Socket.IO pingInterval/pingTimeout explicitly (25s/60s)
instead of relying on defaults.
## JWT Expiration Fixes
1. Increase WebToken DB record expiration from 1 hour to 7 days. The
1-hour expiration was the real session lifetime gate (the JWT crypto
exp was already 24h), and it was far too aggressive for a dev tool.
2. Fix web /auth/renew-token endpoint to use req.user from the session
cookie instead of verifyJsonWebToken(req.body.token). This eliminates
the catch-22 where an expired token cannot be used to request its
own renewal.
3. Fix token refresh response parsing. The API v1 renew-token endpoint
returns { success: true, token } at the top level, but the frontend
was looking for json.data?.token, causing every refresh to fail.
4. Add proactive token refresh: check the JWT exp claim before each
request and refresh if expiring within 5 minutes. This avoids
unnecessary 401 errors and the resulting socket disconnections.
5. Update socket JWT on token renewal via a callback registered in
App.tsx. This ensures that future socket reconnections use the new
token instead of the expired one.
## Files Modified
- gadget-code/frontend/src/workers/heartbeat.worker.ts (NEW)
- gadget-code/frontend/src/lib/socket.ts
- gadget-code/frontend/src/lib/api.ts
- gadget-code/frontend/src/App.tsx
- gadget-code/src/services/session.ts
- gadget-code/src/controllers/auth.ts
- gadget-code/src/services/socket.ts
- gadget-drone/src/gadget-drone.ts
|
||
|---|---|---|
| .opencode/plans | ||
| .vscode | ||
| assets | ||
| docs | ||
| gadget-code | ||
| gadget-drone | ||
| packages | ||
| .gitignore | ||
| AGENTS.md | ||
| gadget.code-workspace | ||
| package.json | ||
| pnpm-lock.yaml | ||
| pnpm-workspace.yaml | ||
| README.md | ||
| terms-of-service.md | ||
Gadget Code
A self-hosted Agentic Engineering Platform (AEP) — an IDE that drives autonomous AI agents to perform software engineering work on your behalf, running in your own environment.
Quick Start
# Install dependencies
pnpm install
# Start backend (Terminal 1)
cd gadget-code
pnpm dev:backend
# Start frontend (Terminal 2)
cd gadget-code/frontend
pnpm dev
# Open browser to https://localhost:5174
Projects
| Package | Role |
|---|---|
gadget-code |
Web service — agentic IDE, browser UI, API server |
gadget-drone |
Worker process — runs the agentic workflow loop in workspace directories |
@gadget/ai |
Shared AI API abstraction — Ollama and OpenAI |
@gadget/api |
Shared TypeScript interfaces — common types across all packages |
Architecture
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Browser IDE │────▶│ gadget-code │────▶│ gadget-drone │
│ (React 19) │◀────│ (Express 5) │◀────│ (Worker) │
└──────────────┘ └──────────────┘ └──────────────┘
│ │ │
│ Socket.IO │ MongoDB │ Files
│ JWT Auth │ Redis │ Git
How It Works
- User creates a project in the browser IDE
- User selects a drone instance to work on the project
- User enters a prompt in the Chat Session view
- Prompt flows IDE → Web → Drone via Socket.IO
- Drone executes the Agentic Workflow Loop (AWL)
- Streaming response flows back: thinking → response → tool calls
- Results persist in MongoDB as ChatTurn records
AI Provider Setup
Before using AI features, add a provider via CLI:
# Add Ollama provider (no API key needed)
cd gadget-code
pnpm cli provider add "Local Ollama" ollama http://localhost:11434
# Add OpenAI provider
pnpm cli provider add "OpenAI" openai https://api.openai.com $OPENAI_API_KEY
# List providers
pnpm cli provider ls
# Probe provider for models (discovers available models)
pnpm cli provider probe <provider-id>
User Management
# Add a user
pnpm cli user add user@example.com password123 "Display Name"
# Grant admin rights
pnpm cli admin grant user@example.com
# Reset password
pnpm cli user password user@example.com newpassword
Development
Prerequisites
- Node.js 22+
- pnpm 10+
- MongoDB on
localhost:27017 - Redis on
localhost:6379 - SSL certificates in
ssl/directory (for dev servers)
Build
# Build all packages
pnpm -r build
# Build specific package
pnpm --filter @gadget/ai build
pnpm --filter gadget-drone build
pnpm --filter gadget-code build
Run Development Servers
# Backend (gadget-code directory)
cd gadget-code
pnpm dev:backend
# Runs on https://localhost:3443
# Frontend (gadget-code/frontend directory)
cd gadget-code/frontend
pnpm dev
# Runs on https://localhost:5174
# Drone worker (in a workspace directory)
cd ~/my-gadget-workspace
pnpm --filter gadget-drone dev
Testing
# Unit tests (gadget-code directory)
cd gadget-code
pnpm test
# E2E tests with Playwright (requires running dev servers)
npx playwright test tests/e2e/project-manager.test.ts
npx playwright test tests/e2e/chat-session.test.ts
# Seed test data for E2E tests
npx tsx scripts/seed-test-drones.ts
Key Features
Project Manager
- Create and manage projects
- Select available drones (filters out offline)
- View chat session history
- Create new chat sessions with provider/model selection
Chat Session View
- Real-time streaming responses
- Collapsible thinking content
- Tool call summaries
- Model/mode selection per session
- Session statistics (tool calls, file ops, subagents)
Workspace Management
- Each drone manages a workspace directory
- Projects cloned into workspace by slug
- Crash recovery via
.gadget/directory - Workspace persistence across restarts
AI API Abstraction
All AI calls route through @gadget/ai. No consumer code imports Ollama or OpenAI SDKs directly.
// Correct: Use the factory
import { createAiApi } from '@gadget/ai';
const ai = createAiApi(providerConfig);
// Incorrect: Don't import SDKs directly
import { Ollama } from 'ollama'; // ❌
See packages/ai/README.md for the full API reference.
Documentation
Monorepo Structure
gadget/
├── packages/ai/ # @gadget/ai — AI API abstraction
├── packages/api/ # @gadget/api — Shared interfaces
├── gadget-code/ # Web service + browser IDE
│ ├── src/ # Backend (Express, Socket.IO, Mongoose)
│ ├── frontend/ # Frontend (React, Vite, Tailwind)
│ └── tests/ # Unit + E2E tests
├── gadget-drone/ # Worker process
│ ├── src/ # Drone implementation
│ └── docs/ # Drone documentation
└── docs/ # Architecture & protocol docs
License
Apache 2.0 — See LICENSE for details.
Status: Production-ready foundation with complete Chat Session UI
Last Updated: April 29, 2026