Commit Graph

246 Commits

Author SHA1 Message Date
Fusion 1f784b552d fix: resolve config folders API bugs and test infrastructure
- Fix validation error handler to serialize ValueError objects safely
- Add GET /config-folders/{id} endpoint (was missing)
- Fix project overrides API to accept project_id in body instead of query param
- Add flag_modified for SQLAlchemy JSONB change detection
- Fix DELETE endpoint to return 204 status code
- Fix conftest.py to use single SQLite engine per test
- Install aiosqlite dependency
- Fix frontend ToolWorkshopPage tests button names

Config folders tests: 13/13 passing
Docker build tests: 10/10 passing
Readiness probe tests: 13/13 passing
2026-05-22 20:16:23 +02:00
Fusion dacf105200 test: add comprehensive tests for tool workshop functionality
Backend tests:
- Unit tests for docker_build service (successful/failed builds, context, paths)
- Unit tests for readiness_probe service (success, timeout, retries, edge cases)
- Integration tests for config_folders API (CRUD + project overrides)
- Integration tests for tool_types API with new fields
- Integration tests for tool_configs API with new fields

Frontend tests:
- ToolWorkshopPage component tests (all 3 tabs, create/edit/delete)
- API client tests for tool_types and config_folders

Fixes:
- Add field_validator import to tool_configs.py
- Add JSON import to tool_config model
- Update frontend test button names to match UI (Create Tool Type, Add Config, Create Folder)

Quality gates: backend unit tests passing (23/23)
2026-05-22 19:45:10 +02:00
Fusion 8dd350286e feat: implement tool workshop - comprehensive tool system enhancement
- Add Docker Compose and Dockerfile support for tool definitions
- Implement readiness probes with configurable command, timeout, interval
- Create ConfigFolder model for reusable file collections with project overrides
- Add rich tool config fields: port_override, start_command, working_directory, env vars, volumes
- Build unified Tool Workshop UI at /tool-workshop replacing /tool-configs and /tool-types
- Update instance creation to support dockerfile builds, config folder mounting, readiness probes
- Add 3 database migrations for tool_types, tool_configs, and new config_folders table
- Create docker_build.py and readiness_probe.py services
- Add config_folders API with CRUD and project override endpoints

Quality gates: frontend build passes, Python syntax valid, all phases complete

Addresses tool-workshop OpenSpec change
2026-05-22 19:06:45 +02:00
Fusion ae377baa74 fix(opencode): add debugging output for installation
- Add set -x for verbose command execution
- Add error messages if npm install fails
- Check which opencode and list global bin directory
- Add npm global bin to PATH in bashrc
- Add ca-certificates package for HTTPS

Quality gates: code review
2026-05-21 12:40:01 +02:00
Fusion a0d4e76662 fix(opencode): ensure proper installation and workspace setup
- Add --unsafe-perm to npm install for global package installation
- Add cd /workspace to /root/.bashrc so terminal opens in repo directory
- Start container process in /workspace directory
- Use exec for proper signal handling

Quality gates: code review
2026-05-21 12:34:18 +02:00
Fusion b61c2256a8 refactor(opencode): install opencode via npm instead of curl
- Replace curl-based installation with npm install -g opencode-ai
- Remove manual PATH setup and symlink creation
- Simplify installation process

Quality gates: code review
2026-05-21 12:29:23 +02:00
Fusion 7e6588a99d fix(opencode): ensure opencode binary is in PATH
- Check if opencode binary exists at expected location before symlinking
- Add ~/.opencode/bin to PATH in /etc/profile and /root/.bashrc
- Provides warning if binary not found instead of silently failing

Quality gates: code review
2026-05-21 12:26:07 +02:00
Fusion 56b54e269a fix(terminal): create PTY for proper interactive shell
- Use Python pty module to create pseudo-terminal
- Pass slave fd to docker exec for real TTY allocation
- Fixes ioctl errors and job control warnings
- Supports terminal resizing via TIOCSWINSZ

Quality gates: local testing
2026-05-21 12:03:36 +02:00
Fusion 6e597b9e21 fix(terminal): allocate proper TTY for docker exec
- Change docker exec -i to -it for real TTY allocation
- Fixes ioctl errors and job control warnings in terminal
- Gives bash a proper terminal for interactive use

Quality gates: manually tested
2026-05-21 11:39:14 +02:00
Fusion a2c3d6877e fix(terminal): remove TTY allocation, use interactive bash with TERM env var 2026-05-21 11:21:51 +02:00
Fusion a200955ef2 fix(terminal): remove duplicate WebSocket read loop, let terminal_manager handle I/O 2026-05-21 11:19:11 +02:00
Fusion 76266fc3d0 fix(terminal): allocate pseudo-TTY for interactive docker exec session 2026-05-21 11:09:08 +02:00
Fusion 9d54a2542b fix(terminal): use decode_session_cookie instead of verify_session_token 2026-05-21 11:05:48 +02:00
Fusion 520078fd64 debug(terminal): add comprehensive logging to WebSocket terminal handler 2026-05-21 11:01:32 +02:00
Fusion 55c4dc1281 fix(git): auto-configure safe.directory when git detects dubious ownership 2026-05-21 10:55:14 +02:00
Fusion 74ac7b00bb fix(logging): add missing import logging to git_files.py 2026-05-21 10:51:27 +02:00
Fusion ecc0acc8dd fix(logging): add detailed error logging to git repository endpoints and utilities 2026-05-21 10:47:30 +02:00
Fusion fba01ddfb2 fix(git): handle empty repositories gracefully and show empty state in UI 2026-05-21 10:38:20 +02:00
Fusion 35a251a0b4 fix(sessions): add tool_type_interfaces to backend response and handle undefined in frontend 2026-05-21 10:19:35 +02:00
Fusion b10eadf64b fix(sessions): navigate to terminal page for terminal-only sessions 2026-05-21 10:14:00 +02:00
Fusion 50fcf5c077 fix(tunnels): skip tunnel creation for terminal-only tools 2026-05-20 18:11:33 +02:00
Fusion 19db7db8d0 fix(compose): remove external network declarations from compose templates 2026-05-20 17:58:36 +02:00
Fusion 189f29ee41 fix(opencode): update seed function to sync existing tool types with code changes 2026-05-20 17:55:18 +02:00
Fusion f2c3264be6 fix(opencode): add tar dependency and symlink binary to /usr/local/bin 2026-05-20 17:48:36 +02:00
Fusion f07a632c86 fix(opencode): use official install script from opencode.ai 2026-05-20 17:37:57 +02:00
Fusion 0b68efb6e0 fix(tunnels): add missing imports for render_compose_template, recreate_tunnel, check_tunnel_health 2026-05-20 17:30:34 +02:00
Fusion 54ec87a836 fix(migration): rename migration to fit within alembic version string limit 2026-05-20 17:24:04 +02:00
Fusion 3d64ec9061 fix(tunnels): connect tool containers to backend network for cloudflared access 2026-05-20 17:21:21 +02:00
Fusion ac6bd3304d feat(opencode-web-terminal): complete OpenCode web terminal implementation
- Update OpenCode compose template with web server on port 3000
- Add default_port=3000 and interfaces=[terminal, web] to OpenCode seed data
- Remove hardcoded 8080 fallback in tunnel creation
- Fail gracefully when tool type has no default_port configured
- Update frontend ToolType API to include default_port, category, interfaces
- Add port, category, and interfaces fields to tool type creation form
- Display port and interfaces in tool type cards
- Create migration 0012 to make default_port non-nullable
- Set default_port values for existing built-in tool types
- Quality gates: typecheck ✓, build ✓, Python syntax ✓
2026-05-20 17:17:50 +02:00
Fusion 6ec35988cc feat(sessions): add stop confirmation, health checks, and tunnel recreation
- Add inline confirmation dialog before stopping instances
- Delete instances from state immediately without page reload
- Add health check polling every 30s for running instances
- Show tunnel error badge when tunnel is unreachable
- Add 'Fix Tunnel' button to recreate broken tunnels
- Update API client with health check and tunnel recreation endpoints
2026-05-20 16:49:31 +02:00
Fusion e985f0122e debug(tunnels): add connectivity check before starting cloudflared tunnel 2026-05-20 16:28:39 +02:00
Fusion 2bd778117f feat(tunnels): switch to temporary Cloudflare tunnels
Replace persistent Cloudflare tunnels (API-based) with temporary tunnels using
'cloudflared tunnel --url'. This removes the need for Cloudflare API tokens,
DNS records, and persistent tunnel management.

Changes:
- Install cloudflared binary in API Dockerfile
- Add start_cloudflared_tunnel() and stop_cloudflared_tunnel() to docker.py
- Update instance start/stop/restart/delete to use temporary tunnels
- Store tunnel PID in tunnel_id field, temporary URL in url/public_url
- Remove Cloudflare API service (cloudflare_tunnel.py)
- Remove cloudflared container from docker-compose
- Remove Cloudflare env vars (CLOUDFLARE_API_TOKEN, ZONE_ID, etc.)
- Remove Cloudflare configuration from config.py
- Remove Cloudflare startup check from main.py
- Remove /health/cloudflare endpoint
2026-05-20 16:23:16 +02:00
Fusion 23ae12e69c debug(cloudflare): add detailed logging for tunnel creation failures 2026-05-20 16:09:47 +02:00
Fusion 65d4fad3c5 fix(cloudflare): fix delete_tunnel subdomain format and add startup config check
- Fix delete_tunnel calls to use correct subdomain format (instance-{id[:8]})
- Add Cloudflare configuration check at startup with clear warnings
- Help diagnose why tunnels aren't being created
2026-05-20 16:01:21 +02:00
Fusion e6f64c39f3 fix(cloudflare): add backend network to compose templates and improve tunnel diagnostics
- Add 'backend' external network to all compose templates so cloudflared can reach tool containers
- Add better error handling and logging to create_tunnel() with specific error messages for auth failures
- Add check_cloudflare_config() diagnostic function
- Add /health/cloudflare endpoint to verify Cloudflare configuration
- Import Any type for type hints
2026-05-20 15:55:20 +02:00
Fusion e7c42c17b9 fix(docker): copy Python packages to root home directory
Since API container runs as root (for Docker socket access),
copy Python packages to /root/.local instead of /home/appuser/.local
so uvicorn and other dependencies are in PATH.
2026-05-20 15:42:12 +02:00
Fusion f7be50952a fix(docker): run API container as root for Docker socket access
The API container needs to run docker compose commands via the
mounted Docker socket. Running as non-root user doesn't work well
with socket permissions across container boundaries.

- Remove USER appuser from Dockerfile (API service only)
- Remove group_add from docker-compose (no longer needed)
- Add security note about considering Docker-in-Docker or rootless

This fixes:
permission denied while trying to connect to the docker API at unix:///var/run/docker.sock
2026-05-20 15:38:02 +02:00
Fusion 402e662c0c fix(docker): add docker group to API container for socket access
The API container needs access to /var/run/docker.sock to run
docker compose commands for tool instances. Add group_add to
match the host's docker GID.

Error was:
permission denied while trying to connect to the docker API at unix:///var/run/docker.sock
2026-05-20 15:33:30 +02:00
Fusion 7450dd0ce5 fix(instances): add missing TOOL_NAME variable to compose template
The compose template uses {{TOOL_NAME}} for container_name but
we weren't passing it in the variables dict, causing YAML parse error.

Error was:
yaml: cannot use 'map[string]interface {}{"TOOL_NAME":interface {}(nil)}' as a map key
2026-05-20 15:30:45 +02:00
Fusion 7a88639250 chore(logging): add detailed debug logging to instance start and tunnel creation
Add comprehensive logging to trace 500 error:
- Log each step of docker compose up (returncode, stdout, stderr)
- Log container ID and name after start
- Log tool type and port being used
- Log each step of Cloudflare tunnel creation with API responses
- Log cloudflared config updates

This will help identify exactly where the failure occurs.
2026-05-20 15:27:55 +02:00
Fusion 1d33735e2f fix(cloudflare): use correct container port in tunnel config
Cloudflared was hardcoded to route to port 8080, but containers
listen on different ports (8443 for code-server, 8888 for jupyter).

- Add instance_port parameter to create_tunnel and update_cloudflared_config
- Fetch tool type default_port when creating tunnels
- Route to correct internal port instead of hardcoded 8080
2026-05-20 15:23:39 +02:00
Fusion d11b43b69f fix(settings): properly save and clear configuration values
Backend:
- Replace dict mutation with dict replacement to fix SQLAlchemy JSON
  mutation tracking issue (config.config = {**config.config, **update_data})

Frontend:
- Send explicit null values instead of undefined so fields can be cleared
- Update UserConfigUpdate interface to accept null values
2026-05-20 15:17:33 +02:00
Fusion 294d02f9fb feat(sessions): add confirmation dialog before deleting active sessions
Active Sessions now show inline confirm/cancel buttons before deletion,
matching the Recent Sessions UX pattern.
2026-05-20 15:14:15 +02:00
Fusion a10029f36c fix(sessions): use session project_id and repository_id for stop/delete
Fix 404 error when stopping or deleting instances from sessions page.
Was passing empty string for repoId instead of session.repository_id.
2026-05-20 15:11:57 +02:00
Fusion 6a2ebae8c9 fix(sessions): auto-start instances and add delete button
- Auto-start instances after creation from Sessions page
- Add delete button to Active Sessions section
- Fix instances remaining in 'pending' status
2026-05-20 15:07:52 +02:00
Fusion 1a922d4171 fix(sessions): correct session state categorization
- Backend now returns stopped and error sessions too
- Active sessions include running/building/pending
- Recent sessions show stopped/error only
- Status badge shows actual status (running/building/pending)
2026-05-20 14:49:30 +02:00
Fusion d906c12aa9 fix(sessions): open Cloudflare URLs directly in all session sections
- Fix Recent Sessions section to use anchor tag linking to instance URL
- Fix Last Session section to show URL and open it directly
- All Open buttons now link directly to Cloudflare URLs instead of navigating to project
2026-05-20 14:45:22 +02:00
Fusion 4906ce0cd9 feat(sessions): display and open Cloudflare URLs in session view
- Show Cloudflare URL in active session cards
- Change Open button to anchor tag linking directly to instance URL
- Add CSS styling for URL display in session cards
- Falls back to project navigation if no URL available
2026-05-20 14:38:33 +02:00
Fusion e7804c0f58 fix(sessions): open instance URL in new tab
Update handleOpen in SessionsPage to open the instance URL
in a new tab when available, instead of navigating to the
project page. Falls back to project navigation if no URL.
2026-05-20 14:28:09 +02:00
Fusion b40eb3e88c feat(cloudflare-tunnel): integrate Cloudflare tunnels for instance access
Backend:
- Add cloudflare_tunnel.py service for creating/deleting tunnels via Cloudflare API
- Add public_url and tunnel_id fields to ToolInstance model
- Update start_instance to create Cloudflare tunnel after container starts
- Update stop_instance to delete tunnel before stopping container
- Update delete_instance to cleanup tunnel before deletion
- Update restart_instance to recreate tunnel on restart
- Create Alembic migration 0011 for tunnel fields
- Add Cloudflare config settings (API token, zone ID, account ID, base domain)

Infrastructure:
- Add cloudflared service to docker-compose.traefik.yml
- Mount shared cloudflared_config volume between API and cloudflared containers
- Add Cloudflare env vars to API service

Frontend:
- Update instance Open button to handle both full URLs and proxy paths

The instance URL is now set to the Cloudflare tunnel public URL when available,
falling back to the API proxy path if tunnel creation fails.
2026-05-20 14:25:06 +02:00