Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
3 changes: 0 additions & 3 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,4 @@
*.log
/*.png
**/*.tsbuildinfo
coverage
node_modules
qa-output
supabase/.temp
6 changes: 0 additions & 6 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,5 @@ indent_size = 2
[*.py]
indent_size = 4

[*.toml]
indent_size = 4

[*.md]
trim_trailing_whitespace = false

[Makefile]
indent_style = tab
4 changes: 0 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,7 @@ node_modules/
.next/
.vercel/
dist/
coverage/
.qa/
qa-output/
qa-*.png
*.har
*.tsbuildinfo
.env
.env.*
Expand Down
5 changes: 0 additions & 5 deletions .vercelignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
# Local documentation and planning directories are not part of the deploy bundle.
/docs/
/tasks/
/plans/
# Build artifacts (match anywhere; Vercel installs + builds fresh)
node_modules
.pnpm-store
Expand All @@ -17,4 +13,3 @@ node_modules
compose.yaml
.dockerignore
infra/containers/dev
supabase
111 changes: 25 additions & 86 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ apps/ Deployable services
webhooks-worker/ Polar/Clerk/Composio webhooks + internal ops workflows

packages/ Shared libraries
agent-core/ Mastra instance + workflows
tools-*/ Tool implementations per domain
agent-core/ Mastra instance, workflows, and data/document/media tools
tools-{browser,code,research}/ Multi-consumer and isolated tool-domain packages
db/ Drizzle schema (per-domain) + queries + migrations
byok/ Vault-backed BYOK key store
skills/ Build-time skill bundler
Expand All @@ -49,9 +49,9 @@ packages/ Shared libraries
types/ Zod schemas + branded IDs + InferAgentUIMessage
ui/ Shared Cheatcode UI primitives, icon barrel, AI response renderer

skills/ 8 curated Anthropic SKILL.md skills
infra/ Wrangler configs, Supabase migrations, Daytona sandbox Dockerfile
scripts/ Operational helpers only: build skills, local startup, deploy orchestration, migrations
skills/ 19 curated skills; _shared/office is vendored and not bundled
infra/ Container images and Dockerfiles for local development and Daytona sandboxes
scripts/ Operational helpers: build-skills, dev, dev-worker-config, jsonc, migrate, migration-drizzle, database-operation-safety
```

## Build
Expand All @@ -73,46 +73,24 @@ pnpm turbo lint # Biome check (fails CI on warnings)
pnpm turbo build # Production build
```

Product/acceptance testing is direct `agent-browser --auto-connect --session cheatcode-debug`
UI interaction only: click/fill/type through real flows, capture screenshots,
inspect console/network output, and read app logs. Do not add or run scripted
test harnesses for product flows, browser automation, prompt submission, auth,
accessibility, load, or final E2E. Package `test` scripts are intentionally not
part of the V2 command surface, and source-level `*.test.ts` files are
intentionally absent. Do not generate temporary validation scripts either;
operate the UI directly and check logs, and remove any throwaway product QA
script that appears in the V2 tree. Operational scripts may exist only for
build, migration, and local-stack configuration; they are not
product tests and must not simulate UI/user flows. Do not create temporary
testing scripts in `scripts/`, package folders, `/tmp`, or any out-of-tree
location.

May 27, 2026 user override: never use scripts for product testing. Product QA
means direct `agent-browser` UI operation, screenshots, console/network
inspection, and running app-log review only. Delete any future V2 product-flow
validator, prompt runner, browser wrapper, or throwaway QA helper on sight
instead of running it. The removed V1 tree must not be restored, copied back,
or used as a source of product-test scripts.

May 28, 2026 hardening: do not wrap product QA in `pnpm`, `tsx`, shell loops,
`/tmp` helpers, generated files, browser-driver wrappers, package aliases, or
any scripted flow. Every product UI action, screenshot, console read,
network/resource inspection, and app-log inspection must be issued directly in
the transcript. Typecheck/lint/build are code-health gates only; they are not
product QA.

May 28, 2026 direct override: delete any product-flow test script, temporary
helper, command-loop runner, browser wrapper, prompt driver, curl flow, or
package alias when discovered. The active V2 tree should contain no product-test
scripts. The remaining `scripts/` files are operational only and must not click
the UI, submit prompts, drive auth, gather acceptance evidence, or replace
direct `agent-browser` operation.

May 28, 2026 latest user directive: code the all-weeks V2 surface first, then
run final product QA only through direct `agent-browser --auto-connect --session
cheatcode-debug` UI actions and direct console/network/app-log inspection. Do
not write, run, or keep scripts to submit prompts, click UI, drive auth, wrap
`agent-browser`, run curl flows, or gather acceptance evidence.
Product/acceptance testing uses only direct
`agent-browser --auto-connect --session cheatcode-debug` commands issued in the
transcript to click, fill, and type through real flows, capture screenshots,
inspect console/network/resources, and read running app logs. Never add, run,
write, or keep scripts for product testing, browser automation, prompt
submission, auth, accessibility, load, or final E2E, including `pnpm`/`tsx`
wrappers, shell or command loops, `/tmp` or generated helpers, browser-driver
wrappers, package aliases, prompt drivers, curl flows, validators, and
throwaway QA helpers in `scripts/`, package folders, or any out-of-tree
location; delete them on sight instead of running them. Package `test` scripts
and source-level `*.test.ts` files remain absent. Operational scripts may exist
only for build, migration, and local-stack configuration and must not click the
UI, submit prompts, drive auth, gather acceptance evidence, or replace direct
browser operation. Typecheck, lint, and build are code-health gates only, not
product QA. Code the all-weeks V2 surface first, then perform final QA through
the direct browser commands and direct console/network/app-log inspection. The
removed V1 tree must not be restored, copied back, used as a testing surface, or
used as a source of product-test scripts.

## Run locally

Expand All @@ -121,47 +99,8 @@ pnpm dev # Compose: Next + chained Workers agains
pnpm dev:down # Stop the local Compose stack
```

Required local env vars in `.env.local` (template in `.env.example`):

```
# Production Supabase session-pooler URLs for the three isolated Worker roles.
# Administrative migration credentials never belong in .env.local.
SUPABASE_GATEWAY_DATABASE_URL=
SUPABASE_AGENT_DATABASE_URL=
SUPABASE_WEBHOOKS_DATABASE_URL=

# Per-Worker signed tenant context (three distinct secrets, each at least 32 bytes)
DATABASE_CONTEXT_SIGNING_SECRET_GATEWAY=
DATABASE_CONTEXT_SIGNING_SECRET_AGENT=
DATABASE_CONTEXT_SIGNING_SECRET_WEBHOOKS=

# Daytona
DAYTONA_API_KEY=
DAYTONA_API_URL=https://app.daytona.io/api
DAYTONA_TARGET=us
DAYTONA_SANDBOX_SNAPSHOT=
DAYTONA_WORKSPACE_VOLUME=cheatcode-workspaces-development
PREVIEW_TOKEN_SECRET=

# Clerk development instance only
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=
CLERK_SECRET_KEY=

# Polar
POLAR_ACCESS_TOKEN=
POLAR_WEBHOOK_SECRET=

# Composio
COMPOSIO_API_KEY=
COMPOSIO_AUTH_CONFIGS={"github":"ac_...","gmail":"ac_...","slack":"ac_...","notion":"ac_...","linear":"ac_..."}
COMPOSIO_WEBHOOK_SECRET=

# Signed output capability
OUTPUT_DOWNLOAD_SIGNING_SECRET=

# Browser-visible local routing configuration (not secrets)
NEXT_PUBLIC_GATEWAY_URL=http://127.0.0.1:8787
```
Copy the complete `.env.local` template from `.env.example`;
`scripts/dev.ts` validates it before local startup.

Never commit `.env.local`. It is the sole laptop application credential file;
its database URLs contain only the three least-privilege production runtime
Expand Down
65 changes: 28 additions & 37 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,9 @@ apps/
webhooks-worker/ Clerk, Polar, Composio webhooks + internal ops workflows

packages/
agent-core/ Mastra agent, workflows, tools, and runtime contexts
agent-core/ Mastra agent, workflows, contexts, and data/document/media tools
tools-code/ Sandbox shell/file/git/runCode tools
tools-browser/ Stagehand LOCAL browser automation
tools-docs/ pptxgenjs, docx, exceljs, @react-pdf/renderer
tools-data/ Arquero CSV analysis + deterministic SVG charts
tools-research/ Exa + Firecrawl
db/ Drizzle schema (per-domain) + queries + migrations
byok/ Vault-backed BYOK with provider validation
Expand All @@ -54,9 +52,9 @@ packages/
ui/ shared UI primitives, icon barrel, AI response renderer
tsconfig/ Shared base/nextjs/worker/library configs

skills/ 8 curated Anthropic SKILL.md skills
infra/ Wrangler configs, Supabase migrations, Daytona sandbox Dockerfile/snapshot
scripts/ Operational helpers only: build skills, local startup, deploy orchestration, migrations, audit archive
skills/ 19 curated skills; _shared/office is vendored and not bundled
infra/ Container images and Dockerfiles for local development and Daytona sandboxes
scripts/ Operational helpers: build-skills, dev, dev-worker-config, jsonc, migrate, migration-drizzle, database-operation-safety
```

## Critical conventions (non-negotiable)
Expand Down Expand Up @@ -89,42 +87,29 @@ pnpm --filter @cheatcode/db db:generate # Create new migration
```

Pre-commit (Lefthook) runs Biome on staged + typecheck on changed packages. Must stay <5s.
Product/acceptance testing is direct `agent-browser --auto-connect --session cheatcode-debug`
UI operation plus console/network/app-log review. Do not add or run scripted
browser/product-flow test harnesses; package `test` scripts and source-level
`*.test.ts` files are intentionally absent from the V2 command surface. Do not generate temporary validation scripts either; operate
the UI directly and check logs, and remove any throwaway product QA script that
appears in the V2 tree. Operational scripts may exist only for build,
migration, secret sync, Docker cleanup, and guarded deploy orchestration; they are not
product tests and must not simulate UI/user flows. Do not create temporary
testing scripts in `scripts/`, package folders, `/tmp`, or any out-of-tree
location. Delete future V2 product validators instead of running them. The
Product/acceptance testing uses only direct
`agent-browser --auto-connect --session cheatcode-debug` commands issued in the
transcript to click, fill, and type through real flows, capture screenshots,
inspect console/network/resources, and read running app logs. Never add, run,
write, or keep scripts for browser or product-flow testing, including
`pnpm`/`tsx` wrappers, shell or command loops, `/tmp` or generated helpers,
browser-driver wrappers, package aliases, prompt drivers, curl flows,
validators, and throwaway QA helpers in `scripts/`, package folders, or any
out-of-tree location; delete them on sight instead of running them. Package
`test` scripts and source-level `*.test.ts` files remain absent. Operational
scripts may exist only for build, migration, secret sync, Docker cleanup, and
guarded deploy orchestration and must not click the UI, submit prompts, drive
auth, gather acceptance evidence, simulate UI/user flows, or replace direct
browser operation. Typecheck, lint, and build are code-health gates only, not
product QA. Code the all-weeks V2 surface first, then perform final QA through
the direct browser commands and direct console/network/app-log inspection. The
removed V1 tree must not be restored or copied back as a testing surface.

May 28, 2026 hardening: do not wrap product QA in `pnpm`, `tsx`, shell loops,
`/tmp` helpers, generated files, browser-driver wrappers, package aliases, or
any scripted flow. Each UI action, screenshot, console read, network/resource
inspection, and app-log inspection must be issued directly in the transcript.
Typecheck/lint/build remain code-health gates only.

May 28, 2026 direct override: delete any product-flow test script, temporary
helper, command-loop runner, browser wrapper, prompt driver, curl flow, or
package alias when discovered. The active V2 tree should contain no product-test
scripts. The remaining `scripts/` files are operational only and must not click
the UI, submit prompts, drive auth, gather acceptance evidence, or replace
direct `agent-browser` operation.

May 28, 2026 latest user directive: code the all-weeks V2 surface first, then
run final product QA only through direct `agent-browser --auto-connect --session
cheatcode-debug` UI actions and direct console/network/app-log inspection. Do
not write, run, or keep scripts to submit prompts, click UI, drive auth, wrap
`agent-browser`, run curl flows, or gather acceptance evidence.

## Where things live

| Need | File |
|---|---|
| Add a new tool | `packages/tools-<domain>/src/<tool>.ts` |
| Add a new tool | `packages/agent-core/src/tools/<domain>/<tool>.ts` for data/docs/media; `packages/tools-<domain>/src/<tool>.ts` for browser/code/research |
| Add a new agent | `packages/agent-core/src/mastra/agents/<name>.ts` |
| Add a new workflow | `packages/agent-core/src/mastra/workflows/<name>.ts` |
| Add a new skill | `skills/<name>/SKILL.md` (+ optional `references/` / `assets/`) |
Expand All @@ -136,7 +121,13 @@ not write, run, or keep scripts to submit prompts, click UI, drive auth, wrap

Curated skills are bundled at build time into `packages/skills/src/generated.ts` (Workers have no filesystem at runtime). Anthropic SKILL.md format. V2 has no bundled skill scripts, no `evals/evals.json`, no local skill-eval runner, and no `skill_run_script` tool.

The source-of-truth catalog is the set of skill folders under `skills/`; do not duplicate a manually maintained name list here. External skill registry exports, skills.sh links, public publishing scripts, and launch-prep copy are outside V2 unless the user explicitly re-expands the plan.
The source-of-truth catalog is the set of non-underscore skill folders under
`skills/`; do not duplicate a manually maintained name list here.
`skills/_shared/office/` is the shared vendored tree materialized by the sandbox
Dockerfile, and `scripts/build-skills.ts` skips `_`-prefixed directories.
External skill registry exports, skills.sh links, public publishing scripts,
and launch-prep copy are outside V2 unless the user explicitly re-expands the
plan.

The bundler contract lives in `scripts/build-skills.ts` and `packages/skills`.

Expand Down
3 changes: 0 additions & 3 deletions apps/agent-worker/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -194,9 +194,6 @@ Mastra tool-call chunks also emit `step_started`, `step_completed`,
live stream. If the last stream subscriber disconnects while a run is still
running, AgentRun emits `run_abandoned` for the watchdog/funnel trail.

AgentRun also emits `data-plan` and `data-task-status` UI chunks so the web app can
render task progress without polling a separate status endpoint.

Project deletion first fences project/thread mutations, refuses an active run, records a
durable cleanup request, then removes that project's workspace folder. The database marks
cleanup complete only after the Agent service succeeds, so a repeated DELETE retries a
Expand Down
1 change: 0 additions & 1 deletion apps/agent-worker/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
"types": "./dist/index.d.ts",
"scripts": {
"build": "wrangler deploy --dry-run",
"deploy": "wrangler deploy",
"lint": "biome check .",
"typecheck": "tsc -p tsconfig.json --noEmit"
},
Expand Down
44 changes: 6 additions & 38 deletions apps/agent-worker/src/agent-api-run-routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
type AgentRunAdmissionOutcome,
activeRunForThreadRoute,
agentRunForRunId,
callAgentRun,
fetchAgentRun,
reconcileAgentRunAdmission,
runEntitlementPolicy,
Expand Down Expand Up @@ -63,7 +64,6 @@ type RejectedRunResult = Exclude<
export function registerAgentRunHttpRoutes(app: Hono<{ Bindings: AgentEnv }>): void {
app.post("/v1/threads/:threadId/runs", createRun);
app.get("/v1/threads/:threadId/runs/stream", streamActiveRun);
app.get("/v1/threads/:threadId/runs/status", activeRunStatus);
app.post("/v1/runs/:runId/cancel", cancelRun);
app.get("/v1/threads/:threadId/browser-takeover", browserTakeoverStatus);
app.post("/v1/threads/:threadId/browser-takeover/start", startBrowserTakeover);
Expand Down Expand Up @@ -276,26 +276,11 @@ async function streamActiveRun(c: AgentContext): Promise<Response> {
);
}

async function activeRunStatus(c: AgentContext): Promise<Response> {
const userId = readGatewayUserId(c.req.raw.headers);
const threadId = parseThreadRouteParam(c.req.param("threadId") ?? "");
const run = await activeRunForThreadRoute(c.env, userId, threadId);
if (!run) {
return new Response(null, { status: 204 });
}
return fetchAgentRun(agentRunForRunId(c.env, run.runId), "https://agent-run.internal/status", {
headers: { "X-Cheatcode-User-Id": userId },
});
}

async function cancelRun(c: AgentContext): Promise<Response> {
const userId = readGatewayUserId(c.req.raw.headers);
const runId = parseRunRouteParam(c.req.param("runId") ?? "");
const run = await runForRoute(c.env, userId, runId);
return fetchAgentRun(agentRunForRunId(c.env, run.runId), "https://agent-run.internal/cancel", {
headers: { "X-Cheatcode-User-Id": userId },
method: "POST",
});
return callAgentRun(agentRunForRunId(c.env, run.runId).cancel(userId));
}

async function browserTakeoverStatus(c: AgentContext): Promise<Response> {
Expand All @@ -304,11 +289,7 @@ async function browserTakeoverStatus(c: AgentContext): Promise<Response> {
if (!run) {
return Response.json(BrowserTakeoverStatusSchema.parse({ status: "inactive" }));
}
return fetchAgentRun(
agentRunForRunId(c.env, run.runId),
"https://agent-run.internal/browser-takeover",
{ headers: { "X-Cheatcode-User-Id": userId } },
);
return callAgentRun(agentRunForRunId(c.env, run.runId).browserTakeoverStatus(userId));
}

async function startBrowserTakeover(c: AgentContext): Promise<Response> {
Expand All @@ -320,11 +301,7 @@ async function startBrowserTakeover(c: AgentContext): Promise<Response> {
retriable: false,
});
}
return fetchAgentRun(
agentRunForRunId(c.env, run.runId),
"https://agent-run.internal/browser-takeover/start",
{ headers: { "X-Cheatcode-User-Id": userId }, method: "POST" },
);
return callAgentRun(agentRunForRunId(c.env, run.runId).browserTakeoverStart(userId));
}

async function resumeBrowserTakeover(c: AgentContext): Promise<Response> {
Expand All @@ -336,17 +313,8 @@ async function resumeBrowserTakeover(c: AgentContext): Promise<Response> {
if (!run) {
return Response.json(BrowserTakeoverResumeResultSchema.parse({ ok: true, status: "inactive" }));
}
return fetchAgentRun(
agentRunForRunId(c.env, run.runId),
"https://agent-run.internal/browser-takeover/resume",
{
body: JSON.stringify(body),
headers: {
"Content-Type": "application/json",
"X-Cheatcode-User-Id": userId,
},
method: "POST",
},
return callAgentRun(
agentRunForRunId(c.env, run.runId).browserTakeoverResume(userId, body.takeoverId),
);
}

Expand Down
Loading