Skip to content

Make BackAI SupportDesk-first and public-ready - #118

Closed
santoshkumarradha wants to merge 35 commits into
mainfrom
supportdesk-first-dx
Closed

santoshkumarradha wants to merge 35 commits into
mainfrom
supportdesk-first-dx

Conversation

@santoshkumarradha

Copy link
Copy Markdown
Member

Summary

  • Reframes the repo around BackAI with SupportDesk AI as the first-run product path.
  • Adds no-key demo mode, request-id cost tracing, customer-to-admin walkthrough, Compose first run, and Railway template support.
  • Adds repo ownership docs, attach-existing-app docs, example capability manifests, and cleans public BackAI naming/DX.

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.py was already dirty locally and is intentionally not included.

santoshkumarradha and others added 30 commits June 8, 2026 00:37
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>
@AbirAbbas

Copy link
Copy Markdown
Contributor

Absorbed into main via #128, which squash-merged the feat/ui-redesign chain — and that chain contains this branch's commits (supportdesk-first-dx → modular-adapter-system → ui-redesign). The SupportDesk-first work is now on main. Closing as superseded, not rejected. 🙏

@AbirAbbas AbirAbbas closed this Jun 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants