The smoke test caught the biggest beta-blocker yet: everything the AI
writes inside the dev container was invisible in the UI because the
Product/Hosting/Infrastructure tabs all read from Gitea + Coolify, not
from the dev container's volume. Plan tab worked; nothing else did.
Two-part fix:
1. lib/dev-container-git.ts — new module with two helpers:
- ensureProjectRepoCloned(): clones the project's Gitea repo into
/workspace/<slug>/ using the AI's gitea token, embedding the auth
into the remote URL so subsequent pushes work without prompts.
Idempotent: tri-state probe handles 'git' (real repo, no-op),
'dir' (path exists from pre-fix AI work, init in place), and
'absent' (full clone). Has an empty-repo fallback for fresh Gitea
repos where 'git clone' warns and produces nothing checked out.
- commitAndPushIfDirty(): stages all changes under /workspace/<slug>,
commits with a one-line message + pushes to origin. Bails fast
with reason='clean' when there's nothing to commit. Never throws.
2. app/api/chat/route.ts wiring:
- Pre-loop: fire-and-forget ensureProjectRepoCloned so the repo is
on disk before the AI's first filesystem-mutating tool call.
- Post-loop: fire-and-forget commitAndPushIfDirty after the assistant
message is persisted; commit message is the assistant's first
sentence (≤180 chars) or 'AI checkpoint' fallback.
- System prompt now tells the AI: project repo is at /workspace/<slug>,
write everything you want in the UI under that path, and don't
manually commit (harness handles it).
Cred plumbing: GITEA_API_URL/GITEA_USERNAME/GITEA_API_TOKEN are read
from process.env in the harness; the dev container never sees the
token outside of the embedded URL. Same blast radius as shell.exec.
Co-authored-by: Cursor <cursoragent@cursor.com>
12 KiB
12 KiB