Make BackAI SupportDesk-first and public-ready - #118
Closed
santoshkumarradha wants to merge 35 commits into
Closed
santoshkumarradha wants to merge 35 commits into
santoshkumarradha wants to merge 35 commits into
Conversation
End-to-end demo of the Shipwright pattern (customer pastes a GitHub
issue → agent reads repo, plans, edits, tests, opens PR). Built on
standard shadcn components with a stub agent so iteration on the UX
is fast; swap in the real SWE-AF library by replacing one file.
## Backend (examples/02-shipwright/)
- `migrations/00001_shipwright.sql` — `shipwright_tasks` +
`shipwright_steps` with RLS policies; auto-touch trigger on
`updated_at`.
- `agents/shipwright/` — AgentField agent.
- `Agent(node_id="shipwright-v2")` + `@app.reasoner execute_task`
- Stub simulates 7 steps × asyncio.sleep totaling ~10s with
deterministic output (status / summary / diff_preview / steps).
- `__capabilities__` reasoner with harness + MCP runner probe.
- Dockerfile mirrors the sample-agent pattern (NODE_ID + PORT +
AGENT_CALLBACK_URL env).
- `handlers/` — Python FastAPI workload-module sidecar.
- Routes: POST /tasks, GET /tasks, GET /tasks/{id},
POST /tasks/{id}/cancel, GET /stats.
- Tenant-bound DB connection via `SET LOCAL app.tenant_id`.
- `_drive_task` runs in `asyncio.create_task` so POST returns
immediately; persists task row + 7 step rows on completion.
- `docker-compose.yml` — compose overlay with shipwright-migrate,
shipwright-agent, shipwright-api services.
## Frontend (apps/customer-app/)
- `(app)/shipwright/page.tsx` — list page with queue table +
new-task form. shadcn Card / Table / Badge / Field / Input /
Textarea / Button. Polls /tasks every 1.5s; status badges
color-coded (queued / running / completed / failed / cancelled);
durations + relative timestamps render live.
- `(app)/shipwright/[id]/page.tsx` — detail with step timeline,
summary card (duration / steps / status), monospace diff preview.
Live-polls every 1s until terminal state.
- `api/customer/shipwright/[...path]/route.ts` — proxy to the
workload-module sidecar; reads session via `auth.api.getSession`,
resolves `lookupCustomerContext(email)` → forwards
`x-af-stack-tenant-id` + `x-af-stack-user-id` headers.
- `components/layout/customer-sidebar.tsx` — replaced "Code Helper"
nav entry with "Shipwright" (Hammer icon).
## Verified E2E
Captured screenshots in `dashboard-screenshots/`:
- shipwright-with-sidebar.png — sidebar nav, Shipwright active
- shipwright-form-filled.png — new-task form filled
- shipwright-queue-mixed.png — list showing Running + Completed
- shipwright-detail-completed.png — full task detail with steps,
summary, diff preview
- shipwright-agent-logs.txt — agent log lines from the 3 runs
## Gotchas baked into the README + code comments
1. Don't name a reasoner `run` — collides with `Agent.run()` (the
decorator overrides the method; agent exits immediately).
2. AgentField caches reasoner metadata keyed on node_id. After
renaming a reasoner, bump the node_id to force fresh registration.
3. Reasoner payload shape: `{"input": {"payload": {...}}}` for
signatures like `async def f(payload: dict)`.
4. Result shape: runtime returns `{"result": {...}}`, not `output`.
## Swapping in real SWE-AF
Replace `agents/shipwright/main.py` with the real SWE-AF agent.
Keep the node_id + reasoner name + RunResult schema. Everything
else (UI, workload module, DB, polling) is unchanged.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The Shipwright workload module now routes to the actual SWE-AF library
at /Users/santoshkumarradha/Documents/agentfield/code/examples/af-swe by
default. The iteration stub remains available behind an env flag.
## Compose
- swe-af-agent service added — builds from the real af-swe Dockerfile
(gh CLI + OpenCode + Claude Agent SDK + git). Registers as node_id
`swe-planner` with 34 reasoners (build, plan, execute, resolve,
resume_build, plus 29 specialist reasoners: run_coder, run_qa,
run_code_reviewer, run_github_pr, run_ci_fixer, run_replanner, etc.).
- shipwright-agent (the stub) stays running for fast UI iteration.
- swe-af-workspaces named volume persists build artifacts.
## handler.py — sync + async modes
- `SHIPWRIGHT_AGENT` env var selects the agent (default
`swe-planner.build`; `shipwright-v2.execute_task` for the stub).
- `SHIPWRIGHT_MODE=async` posts to `/api/v1/agents/async/<name>` and
polls `/api/v1/runs/{run_id}/agentfield` every 5s for up to 1 hour.
This is the only path that works for real SWE-AF builds (which take
minutes-to-hours).
- `SHIPWRIGHT_MODE=sync` keeps the original inline pattern for the
stub.
- `_build_payload()` translates the customer-app form into either
shape: the stub's `{payload: {...}}` or SWE-AF's `{goal, repo_url,
artifacts_dir, ...}`.
- `_persist_result()` handles both response shapes — coerces SWE-AF's
BuildResult schema (pr_url, repos, plan, diff) to the canonical
{status, summary, diff_preview, steps} the UI expects.
## .env additions
- SHIPWRIGHT_AGENT=swe-planner.build (default — the real SWE-AF)
- SHIPWRIGHT_MODE=async
## Verified E2E
Submitted "[real SWE-AF] hello docs" via the customer-app UI. The
workload module posted /api/v1/agents/async/swe-planner.build with
goal + repo_url. The runtime routed to the SWE-AF agent. The build
reasoner started, attempted git clone of the target repo, and failed
with `could not read Username for 'https://github.com'` — expected
because GH_TOKEN isn't set on this dev box.
Screenshots captured:
- operator-home.png — operator dashboard after first signup
- operator-agents-with-sweaf.png — Build > Agents tab
- agentfield-with-swe-planner.png — AgentField shows 4 build runs
(real SWE-AF) + execute_task runs (stub) side by side
- agentfield-swe-af-run-detail.png — full run detail in AgentField's
UI showing the actual git clone error from the SWE-AF pipeline
## Operator credentials
- Customer: demo@shipwright.test / DemoPassword123!
- Operator: admin@af-stack.test / AdminPassword123!
## To actually complete a SWE-AF build
Set these in .env then `docker compose up -d swe-af-agent`:
- ANTHROPIC_API_KEY (or CLAUDE_CODE_OAUTH_TOKEN) — for Claude Code
- GH_TOKEN — for git clone + PR creation
- OPENROUTER_API_KEY — for the harness model fallback
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contributor
|
Absorbed into |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Verification
ruby -e 'require "yaml"; ...' examples/*/capabilities.yaml\n-rg -n "coming soon|SWE-AF|AF Stack" ...returned no public-surface hits\n-docker compose config --quiet\n-pnpm --dir apps/customer-app exec tsc --noEmit --pretty false\n-pnpm --dir apps/dashboard exec tsc --noEmit --pretty false\n-python3 -m json.tool deploy/railway/railway.json\n-python3 scripts/validate-deploy-targets.py\n-GOCACHE=/tmp/backai-go-build go test ./services/runtime/...\n-pnpm --dir apps/customer-app build\n-pnpm --dir apps/dashboard build\n\n## Notes\n- Build warnings remain for the existing Next.js middleware-to-proxy deprecation.\n-examples/02-shipwright/handlers/handler.pywas already dirty locally and is intentionally not included.