Skip to content

souvikroy/AI-upwork

Repository files navigation

ctobrain.ai

your CTO, on autopilot.

Single-chat autopilot for CEOs running outsourced or GCC engineering teams. The CEO describes what they want; ctobrain.ai produces typed artifacts (PRD, ERD, OpenAPI, SQL, WBS, epics, tasks, Gantt, resource plan, headcount, budget, Upwork post, screening rubric, …) and takes draft-then-approve actions across GitHub / Slack / Linear / Vercel / AWS / Azure / GCP / Supabase / Upstash / Sentry. Layered on top of Upwork — humans do the work; v1 hands off to Upwork manually (no Upwork API).

Plan: see the approved plan in ~/.claude/plans/i-want-to-create-ctobrain.ai.md.

Stack

  • Web — Next.js 14 (App Router) + TypeScript + Tailwind, single chat UI with SSE consumer.
  • API — FastAPI (Python 3.11) + Anthropic SDK + SQLAlchemy + sse-starlette.
  • DB — Postgres 16 + pgvector (Supabase in prod, pgvector/pgvector:pg16 Docker image locally).

Repo layout

apps/
  web/                Next.js chat UI
  api/                FastAPI orchestrator + AI services + tool adapters
infra/
  docker-compose.yml  postgres + api for local dev
  supabase/migrations/0001_init.sql   authoritative DB schema
PRD_template.md       original PRD template (also copied into apps/api/templates)

Prerequisites

  • Node 20+ and pnpm 9+
  • Python 3.11+
  • Docker (for local Postgres) — or use a Supabase project URL directly
  • An Anthropic API key with access to the Claude Opus 4.7 model

First-time setup

# 1. Clone, install root + web deps
pnpm install

# 2. Set up env
cp .env.example .env
# Edit .env — at minimum set ANTHROPIC_API_KEY.
# Generate a tool credential encryption key:
python3 -c "import nacl.utils,base64;print(base64.b64encode(nacl.utils.random(32)).decode())"
# Paste into TOOL_CREDS_ENCRYPTION_KEY=

cp apps/web/.env.local.example apps/web/.env.local
# Edit if you change the API port

# 3. Install API deps
cd apps/api
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
cd ../..

# 4. Boot Postgres locally (auto-applies the migration)
docker compose -f infra/docker-compose.yml up -d postgres

Run locally (two terminals)

Terminal 1 — API:

cd apps/api
source .venv/bin/activate
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000

Terminal 2 — Web:

pnpm --filter ctobrain-ai-web dev

Open http://localhost:3000.

Smoke test

# health
curl http://localhost:8000/healthz

# chat (SSE stream)
curl -N -X POST http://localhost:8000/api/chat \
  -H 'Content-Type: application/json' \
  -d '{"message":"Build a localised iOS App Store recommendation engine for tier-2/3/4 India users. Two-month timeline, ₹8L budget."}'

You should see SSE events: statusintent (structured JSON) → delta… (streaming reply) → done.

In the browser at http://localhost:3000, send the same message — the Goal · confidence chip and constraint pills appear, followed by the streaming assistant reply.

What's built (end-to-end v1)

Backend (FastAPI)

  • app/llm.py — Anthropic streaming + structured tool-use with system-prompt caching.
  • app/services/schemas.py — comprehensive Pydantic types for every v1 artifact.
  • app/services/registry.py — 29 LLM-backed services registered by name (one prompt + one schema each).
  • app/services/deterministic.py — pure-Python services: critical_path (CPM forward+backward pass), gantt_builder, budget_planner.
  • app/services/pipeline.py — 23-stage canonical pipeline (PRD → ERD → … → Onboarding) executed as an async generator, persisting artifacts as it goes.
  • app/orchestrator.py — turn loop: Intent → confidence gate → pipeline → tool ApprovalCards → MemoryExtractor → streamed summary.
  • app/tools/base.py + app/tools/adapters.py — ToolAdapter Protocol + ten v1 adapters (GitHub / Slack / Linear / Vercel / Sentry / AWS / Azure / GCP / Supabase / Upstash). Adapters return simulated=True until real OAuth lands per phase.
  • app/tools/actions.py — composes ApprovalCards from pipeline output.
  • app/state.py — single-tenant in-memory store for sessions, artifacts, approvals, project memory (DB upgrade is one swap).
  • app/main.py — REST endpoints: /healthz, /api/services, /api/sessions (POST+GET), /api/chat (SSE), /api/sessions/{id}/artifacts, /api/approvals (GET), /api/approvals/{id}/decision (POST), /api/projects/{id}/memory (GET+DELETE).

Prompts (29 total) in apps/api/prompts/: intent, planner, spec_builder, prd_creator, erd_creator, api_contract, data_model, wbs_builder, epic_creator, task_creator, acceptance_criteria, dependency_mapper, timeline_planner, resource_planner, headcount_planner, rate_card_manager, upwork_post, screening_rubric, vendor_scorer, interview_scripter, onboarding_checklist, risk_register, test_plan, progress_tracker, status_report, blocker_escalator, change_request, memory_extractor, approval_card.

Frontend (Next.js 14)

  • apps/web/lib/sse.ts — typed SSE client + decideApproval REST helper.
  • apps/web/components/ChatPane.tsx — split-pane chat; left side streams the conversation with intent chip, constraint pills, stage timeline pills, clarify card, memory chip; right side is the artifact drawer.
  • apps/web/components/ArtifactCard.tsx — renders every artifact kind (PRD/Upwork post markdown; ERD with mermaid + collapsible sections; OpenAPI/SQL/Gantt code blocks; Tasks/Epics/Timeline/Resource/Headcount/RateCard/Budget/Risk tables; Screening/Interview/Onboarding panels).
  • apps/web/components/ApprovalCard.tsx — risk-coloured card with Approve / Reject buttons that call the backend.

Databaseinfra/supabase/migrations/0001_init.sql covers all tables incl. pgvector indexes for session embeddings + best-practices library.

State store (Redis)apps/api/app/state/ is a Redis-backed state layer. Every state mutation publishes a JSON event onto a per-session pub/sub channel so the UI streams updates without polling. What's tracked, in detail:

  • Session FSM (11 states): created → extracting_intent → awaiting_clarification | running_pipeline → composing_approvals → awaiting_approvals → executing_approval → extracting_memory → drafting_reply → completed | failed. Each transition is appended to a state log with from, to, at, optional note.
  • Per-stage FSM (one per pipeline stage, 23 stages by default): pending → running → completed | failed | skipped. Each stage record carries started_at, completed_at, duration_ms, per-stage tokens_input/output/cache_read/cache_write, cost_inr, attempts, optional error and artifact_id.
  • Approval FSM: pending → approved | rejected → executing → executed | failed with timestamps for created_at, decided_at, executed_at. Backend counters (approval_pending/approved/rejected/executed/failed) are kept in lock-step with state changes.
  • Aggregated metrics: input/output/cache tokens summed across all Claude calls; running cost in INR + USD using Claude Opus 4.7 list pricing (configurable in app/state/pricing.py).
  • Pipeline metrics: pipeline_started_at, pipeline_completed_at, pipeline_duration_ms, stages_total/completed/failed, current_stage, last_stage, last_error.
  • Memory state: facts_count, rules_count per project, bubbled to every session of that project on update.
  • Static label dictionary at GET /api/state/labels returning the full description for every session/stage/approval state value.

Redis key schema (prefixed zb:) — see apps/api/app/state/keys.py.

End-to-end validation

Validation against a real Redis (db 15, flushed at start) and a mocked Anthropic client:

# Prerequisites: Redis listening on localhost:6379 (docker compose -f infra/docker-compose.yml up -d redis)
cd apps/api
python3.12 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
python3 scripts/validate_e2e.py

Expected output:

=== ctobrain.ai end-to-end validation (Redis) ===
events received from chat: 67
  artifacts:        23
  approvals:        10 (['github', 'linear', 'sentry', 'slack', 'vercel'])
  stages started:   23
  delta chunks:     3

Redis snapshot:
  session.state:        completed
  stages_completed:     23 / 23
  pipeline_duration_ms: 65
  tokens.input:         2280
  tokens.output:        4520
  tokens.cache_read:    1140
  cost_inr:             ₹31.12
  cost_usd:             $0.375
  approvals.pending:    10
  approvals.executed:   1
  memory.facts_count:   1
  memory.rules_count:   1
  state_log entries:    8
  pubsub events:        113

OK — Redis state populated, FSM reached `completed`, tokens + cost aggregated, approval lifecycle works.

The script also exercises the approval FSM by transitioning a GitHub card through pending → approved → executing → executed and re-verifying counters.

Additional checks already run:

  • python3 -m compileall -q app — all Python sources parse cleanly.
  • pnpm --filter ctobrain-ai-web typecheck — TypeScript clean.
  • pnpm --filter ctobrain-ai-web build — Next.js production build succeeds.
  • uvicorn app.main:app — FastAPI boots with 29 services + 10 tools registered.

What's NOT yet wired (and why)

  • Real OAuth for the 10 integrations. Adapters return simulated=True from execute(). Wiring real SDK calls is per-phase work (P5/P6/P7) — the Protocol shape and approval flow are stable, so swap-in is mechanical.
  • DB persistence. State currently lives in app/state.py (in-memory); the schema is already in infra/supabase/migrations/0001_init.sql and SQLAlchemy models in app/db/models.py mirror it. Swap is one file (STORE = StateStore()STORE = SqlStateStore(get_db)).
  • pgvector RAG. Tables + indexes exist in the migration; ContextSearch service is registered in the planner space but not yet plumbed into the canonical pipeline (will be added in P3 follow-up).
  • Project memory rollup. Session-scoped memory updates are persisted; the cross-session rollup job is deferred to P7.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors