debutly 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +662 -0
- package/README.md +192 -2
- package/bin/debutly.mjs +8 -0
- package/drizzle/0000_init.sql +107 -0
- package/drizzle/0001_predictions.sql +14 -0
- package/drizzle/0002_dashboard.sql +15 -0
- package/drizzle/meta/0000_snapshot.json +722 -0
- package/drizzle/meta/0001_snapshot.json +821 -0
- package/drizzle/meta/0002_snapshot.json +942 -0
- package/drizzle/meta/_journal.json +27 -0
- package/package.json +83 -4
- package/src/agent/describe.ts +29 -0
- package/src/agent/effect.ts +94 -0
- package/src/agent/give-up.ts +42 -0
- package/src/agent/label.ts +19 -0
- package/src/agent/loop.ts +302 -0
- package/src/agent/parse-reply.ts +127 -0
- package/src/agent/prompt.ts +85 -0
- package/src/agent/run-agent.ts +68 -0
- package/src/artifacts/db.ts +55 -0
- package/src/artifacts/s3.ts +36 -0
- package/src/artifacts/store.ts +26 -0
- package/src/bin.ts +140 -0
- package/src/browser/ax.ts +77 -0
- package/src/browser/execute.ts +401 -0
- package/src/browser/observe.ts +62 -0
- package/src/browser/reflow.ts +73 -0
- package/src/browser/samples.ts +119 -0
- package/src/browser/scan-script.ts +108 -0
- package/src/browser/settle.ts +32 -0
- package/src/browser/signals.ts +73 -0
- package/src/cancel.ts +20 -0
- package/src/cli.ts +281 -0
- package/src/config.ts +62 -0
- package/src/cost/estimate.ts +32 -0
- package/src/cost/prices.ts +32 -0
- package/src/cost/tiers.ts +27 -0
- package/src/costs.ts +96 -0
- package/src/crew/run-unit.ts +62 -0
- package/src/detect/findings.ts +649 -0
- package/src/detect/wcag.ts +38 -0
- package/src/doctor.ts +145 -0
- package/src/hear-cli.ts +137 -0
- package/src/hear.ts +309 -0
- package/src/import.ts +108 -0
- package/src/inbox/mailpit.ts +46 -0
- package/src/inbox/types.ts +10 -0
- package/src/init.ts +184 -0
- package/src/llm/anthropic.ts +41 -0
- package/src/llm/credits.ts +35 -0
- package/src/llm/factory.ts +65 -0
- package/src/llm/meter.ts +39 -0
- package/src/llm/openai-compatible.ts +90 -0
- package/src/llm/openrouter.ts +9 -0
- package/src/llm/scripted.ts +18 -0
- package/src/llm/types.ts +36 -0
- package/src/perceive.ts +150 -0
- package/src/perception/aggregate.ts +111 -0
- package/src/perception/compare.ts +77 -0
- package/src/perception/evaluate.ts +83 -0
- package/src/perception/exhibits.ts +146 -0
- package/src/perception/market-context.ts +50 -0
- package/src/perception/run-perception.ts +178 -0
- package/src/persona/generate.ts +92 -0
- package/src/persona/inclusion.ts +53 -0
- package/src/persona/language.ts +59 -0
- package/src/persona/people.ts +32 -0
- package/src/predictions.ts +33 -0
- package/src/queue/dispatch.ts +18 -0
- package/src/queue/jobs.ts +28 -0
- package/src/queue/processor.ts +42 -0
- package/src/report/fix-first.ts +121 -0
- package/src/report/launch-readiness.ts +106 -0
- package/src/report/markdown.ts +202 -0
- package/src/run.ts +141 -0
- package/src/sandbox/outbox.ts +65 -0
- package/src/store/db.ts +40 -0
- package/src/store/import-run.ts +116 -0
- package/src/store/pg-run-store.ts +163 -0
- package/src/store/predictions.ts +70 -0
- package/src/store/run-store.ts +78 -0
- package/src/store/schema.ts +193 -0
- package/src/store/url.ts +15 -0
- package/src/types.ts +201 -0
- package/src/util/chromium.ts +20 -0
- package/src/util/json.ts +7 -0
- package/src/util/key-defaults.ts +34 -0
- package/src/util/legacy-env.ts +14 -0
- package/src/util/load-env.ts +28 -0
- package/src/util/pool.ts +12 -0
- package/src/util/run-origin.ts +27 -0
- package/src/worker.ts +53 -0
- package/tsconfig.json +13 -0
package/README.md
CHANGED
|
@@ -1,3 +1,193 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Debutly
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://debutly.dev)
|
|
4
|
+
|
|
5
|
+
**Rehearse your launch.** Debutly sends AI agents through your web app as if they were your first customers. In a real browser they sign up, confirm their email, pick a plan, invite teammates and use the product. Then they tell you what broke, where they got stuck and where they gave up, with the steps to reproduce it, screenshots, and how many agents hit each problem.
|
|
6
|
+
|
|
7
|
+
Run it before a launch, on every pull request, or on a schedule against a throwaway copy of your app.
|
|
8
|
+
|
|
9
|
+
> **Only point Debutly at a test, staging or throwaway copy of your app, never production.** Agents create accounts, submit forms and, in test mode, pay.
|
|
10
|
+
|
|
11
|
+
Website and docs: [debutly.dev](https://debutly.dev) ([quick start](https://debutly.dev/docs/quick-start)). Created by [Chetan Sroay](https://github.com/sroay). Status: early. Flags, the report format and the database schema may still change.
|
|
12
|
+
|
|
13
|
+
## What it does
|
|
14
|
+
|
|
15
|
+
- **Customers in a real browser.** Agents (Playwright and Chromium) click, type, pick options in native and custom dropdowns, upload files (a sample photo or CV made up on the spot), follow links from emails, and wait for slow pages like a person would.
|
|
16
|
+
- **Business crews.** With `--unit business`, an owner signs up, chooses a plan within a budget and invites teammates. Each teammate accepts by email and uses the product in their own login, so invites, roles and shared workspaces get tested too.
|
|
17
|
+
- **Agents with access needs.** The first agents in each run act out an access need: one hears what a screen reader would and works by keyboard only; one works at about 200% zoom; one is on a throttled connection; one reads as a non-native English speaker. The screen-reader agent hears the names the browser gives assistive technology and works by keyboard only, so controls the keyboard can't reach are reported. The low-vision agent's pages are also measured at 320 pixels wide for sideways scrolling. Findings name the related WCAG criteria, for a person to check. They are not an accessibility audit.
|
|
18
|
+
- **Heard with a real screen reader.** `npx debutly hear` opens each page that had a screen-reader finding with NVDA (Windows) or VoiceOver (macOS) running, presses Tab through it, and marks each finding confirmed or not from what the screen reader said about that very control. On three open-source apps, NVDA bore out most such findings and showed which ones to leave out.
|
|
19
|
+
- **Findings with evidence.** Server and page errors, broken journeys, pages that take over 10 s to arrive, controls that something keeps covering, unlabeled buttons and fields, and agents going round in circles. Each comes with repro steps, screenshots and a confidence level.
|
|
20
|
+
- **Knows a test environment from a bug.** If your app has a sandbox that records what it blocked (emails, payments, outside APIs), Debutly reads it and files failures the test environment caused separately from real bugs.
|
|
21
|
+
- **What buyers think.** Cheap "skeptical buyer" evaluators judge your landing and pricing pages, grounded in competitors' own pricing pages. They compare A/B variants and work at the idea stage, before anything is built.
|
|
22
|
+
- **A dashboard.** Runs, findings across runs (new, recurring, gone), step-by-step replays with screenshots, and spend.
|
|
23
|
+
- **Costs under control.** Every run prints an estimate before it starts, and `--max-cost` refuses runs that could cost more. A key with a spending limit is checked before a run starts, and if the provider runs out of credit part-way, every agent stops at its next step and the report says the run was cut short. Bring your own model key; a quick run costs cents.
|
|
24
|
+
|
|
25
|
+
## Quick start
|
|
26
|
+
|
|
27
|
+
Needs Node.js 20.12 or later. In your app's folder:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npx debutly init # a few questions, then a debutly.json
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Put a model key in a `.env` file there (`DEBUTLY_API_KEY=sk-or-…`, from [openrouter.ai/keys](https://openrouter.ai/keys)); init keeps `.env` out of git. One key is all it needs: Debutly picks the models from it. Start a test copy of your app, then:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npx debutly doctor # checks the key, the browser, the config and that the app answers
|
|
37
|
+
npx debutly # runs the agents
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
The first run downloads Chromium (about 150 MB, once). The report lands in `.debutly/runs/<timestamp>/report.md`, next to `sessions.json`, `findings.json` and the screenshots. Flags override `debutly.json` for one run, for example `npx debutly --tier standard --max-cost 3`; `npx debutly --help` lists the commands.
|
|
41
|
+
|
|
42
|
+
`debutly.json` holds the settings, named like the flags below (`maxCost` for `--max-cost`):
|
|
43
|
+
|
|
44
|
+
```json
|
|
45
|
+
{
|
|
46
|
+
"url": "http://localhost:3000",
|
|
47
|
+
"goal": "Sign up, choose a plan and invite a teammate",
|
|
48
|
+
"icp": "Owners of small marketing agencies, 2-15 people",
|
|
49
|
+
"unit": "business",
|
|
50
|
+
"tier": "quick",
|
|
51
|
+
"maxCost": 1
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Options
|
|
56
|
+
|
|
57
|
+
- `--unit individual` (default) simulates one person per unit. `--unit business` simulates business crews: an owner and `--employees` teammates (default 2, max 4; 0 = owner only). `--agents` is the number of units. Crews need `--mailpit`.
|
|
58
|
+
- `--tier quick|standard|deep` sets the run size: Quick is 3 units with owners only, Standard is 10 units with 2 employees each, Deep is 30 units with 3 each. `--agents` and `--employees` override it. `--max-cost 0.50` refuses to start a run that could cost more.
|
|
59
|
+
- `--inclusion off` skips the inclusion needs, which are on by default. The starting need rotates daily.
|
|
60
|
+
- `--languages ar,en` gives the customers first languages in turn. Arabic-first agents browse with their browser set to Arabic, use the site in Arabic when it offers it, write their names in Arabic script and type numbers with Arabic-Indic digits.
|
|
61
|
+
- `--mailpit http://127.0.0.1:54324` gives each agent its own inbox for magic links and confirmation emails, for example the Mailpit that `supabase start` runs.
|
|
62
|
+
- `--sandbox-outbox <url>` (with `DEBUTLY_SANDBOX_TOKEN` set) reads what your app's sandbox blocked during the run. Failures that happened while it was blocking an outside service, server errors saying a key is missing, and failures to reach a website an agent made up for its company are listed under "Caused by the test environment" instead of as findings.
|
|
63
|
+
- `--max-steps`, `--agent-token-cap 200000` and `--agent-minutes 15` cap each agent.
|
|
64
|
+
- Ctrl+C lets agents stop at their next step and still writes the report; a second Ctrl+C quits at once.
|
|
65
|
+
|
|
66
|
+
## What buyers think: perception and experiments
|
|
67
|
+
|
|
68
|
+
Besides agents who use the product, breadth evaluators judge what it shows, like skeptical buyers on a budget. Each must name at least two concrete objections before scoring, and defaults to "no". They need no browser, so hundreds cost cents.
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
# Your pages, grounded in competitors' own pricing pages:
|
|
72
|
+
npx debutly perceive --icp "…" --url https://app.test/ --url https://app.test/pricing \
|
|
73
|
+
--competitors https://rival.test/pricing,https://other.test/pricing
|
|
74
|
+
# An experiment: which version do buyers pick? (a URL or a text file per variant)
|
|
75
|
+
npx debutly perceive --icp "…" --variant A=https://app.test/pricing --variant B=pricing-b.md
|
|
76
|
+
# Idea stage, before anything is built:
|
|
77
|
+
npx debutly perceive --icp "…" --file pitch.md
|
|
78
|
+
# After a normal run: evaluators judge the pages the agents saw
|
|
79
|
+
npx debutly … --evaluators 50
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
- **Sizes:** `--tier quick|standard|deep` gives 50, 300 or 1,500 evaluators.
|
|
83
|
+
- **The report** (`launch-readiness.md`) ranks blockers and objections, compares variants with a 95% interval (and says when a lead could be noise), and suggests fixes. It is always labelled as simulated evidence, with no conversion rates.
|
|
84
|
+
- **Predictions:** with `--store`, each prediction (winner, top objection, intent share) is saved. Record what really happened with `npx debutly predictions record <id> <actual>` and see accuracy with `npx debutly predictions accuracy`.
|
|
85
|
+
|
|
86
|
+
## Run it on a schedule in GitHub Actions
|
|
87
|
+
|
|
88
|
+
The safest place to run Debutly is a throwaway copy of your app, built fresh on the CI runner and deleted afterwards: your real schema, an empty database, test keys only. Your code and keys never leave your own CI. `npx debutly init` can write this workflow for you.
|
|
89
|
+
|
|
90
|
+
```yaml
|
|
91
|
+
# .github/workflows/debutly.yml in your app's repo, next to debutly.json
|
|
92
|
+
name: debutly
|
|
93
|
+
on:
|
|
94
|
+
schedule: [{ cron: "0 4 * * 1" }] # Mondays
|
|
95
|
+
workflow_dispatch:
|
|
96
|
+
jobs:
|
|
97
|
+
agents:
|
|
98
|
+
runs-on: ubuntu-latest
|
|
99
|
+
timeout-minutes: 45
|
|
100
|
+
steps:
|
|
101
|
+
- uses: actions/checkout@v4
|
|
102
|
+
- run: | # start a test copy of your app (seeded database, test keys only)
|
|
103
|
+
npm ci && npm run build
|
|
104
|
+
PORT=3000 npm start &
|
|
105
|
+
- uses: sroay/debutly@v0
|
|
106
|
+
with:
|
|
107
|
+
api-key: ${{ secrets.DEBUTLY_API_KEY }}
|
|
108
|
+
# store-url: ${{ secrets.DEBUTLY_STORE_URL }} # optional: record runs for the dashboard
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
The action waits for the app to answer, runs the agents with the settings in `debutly.json`, puts the report on the run's summary page and attaches the screenshots as the `debutly-report` artifact. Its inputs (`url`, `goal`, `icp`, `tier`, `max-cost`, which defaults to 1.00, and `args` for any other flags) override `debutly.json`.
|
|
112
|
+
|
|
113
|
+
## Dashboard
|
|
114
|
+
|
|
115
|
+
`dashboard/` is a Next.js app that reads the database runs are recorded into:
|
|
116
|
+
- **Overview:** each app's latest run, a trend of recent runs, and open bugs.
|
|
117
|
+
- **Runs:** every run, by app, with each business crew and agent and how far they got. Findings are split three ways: bugs in the app, doubtful, and caused by the test environment.
|
|
118
|
+
- **Replays:** each agent's run step by step, with the screenshot, what it did, why, and what happened next.
|
|
119
|
+
- **Findings:** every finding across runs, marked as new, recurring, or not in the latest run.
|
|
120
|
+
- **Spend:** model cost per day and app.
|
|
121
|
+
|
|
122
|
+
Any Postgres works, and a free one (Neon, Supabase) is enough. With `--store` and no S3 configured, screenshots are kept in the database as compact JPEGs and pruned after `--screenshot-days` (7 by default).
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
# Record a run:
|
|
126
|
+
npx debutly … --store "$DATABASE_URL" --app my-app
|
|
127
|
+
# Load earlier runs from GitHub Actions report artifacts (needs the gh CLI):
|
|
128
|
+
npx debutly import --store "$DATABASE_URL" --github owner/repo --app my-app
|
|
129
|
+
# Run the dashboard locally (DATABASE_URL in dashboard/.env.local; pglite:<folder> works without a server):
|
|
130
|
+
npm run dashboard
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
**Hosting on Vercel:** set the Root Directory to `dashboard` and add `DATABASE_URL` and `DASHBOARD_PASSWORD`. Connection strings can be pasted exactly as your host gives them. Without `DASHBOARD_PASSWORD`, a deployed dashboard refuses everyone; only `next dev` is open.
|
|
134
|
+
|
|
135
|
+
## Self-hosted stack and scaling out
|
|
136
|
+
|
|
137
|
+
By default a run writes files and needs nothing else. To record every run in a database and spread agents over several workers:
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
docker compose up -d --build # Postgres, Redis, S3-compatible storage, 1 worker (settings from .env)
|
|
141
|
+
docker compose up -d --scale worker=4 # more agents at once
|
|
142
|
+
docker compose --profile smoke run --rm smoke # end-to-end check, about $0.01 of model usage
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Then add `--store postgres://debutly:debutly@localhost:5433/debutly` and `--queue redis://localhost:6380` to a run. `npx debutly cancel <runId> --store <url>` stops a run from anywhere. Workers in Docker reach public (staging) URLs; for an app running on your machine, run workers natively with `npx debutly worker`.
|
|
146
|
+
|
|
147
|
+
## Models and costs
|
|
148
|
+
|
|
149
|
+
Any OpenAI-compatible provider works (`DEBUTLY_PROVIDER=openai-compatible`, for example OpenRouter), or Anthropic (`DEBUTLY_PROVIDER=anthropic`). With OpenRouter, requests go only to providers that keep no copy of prompts and don't train on them (`DEBUTLY_ZERO_RETENTION=off` allows any); [Data and privacy](https://debutly.dev/docs/data-and-privacy) lists what leaves your machine. Set the model that drives the agents with `DEBUTLY_NAV_MODEL` and the one that judges and evaluates with `DEBUTLY_JUDGE_MODEL`.
|
|
150
|
+
|
|
151
|
+
What has worked well: `z-ai/glm-5.3-flash` with `DEBUTLY_REASONING_EFFORT=low` for the agents (allow about 40% more `--max-steps` than Gemini needs), and `deepseek/deepseek-v4-flash` for the judge and evaluators. `google/gemini-3.8-flash` is faster and needs fewer steps but costs about 4× as much per run; `DEBUTLY_NAV_ROUTING='{"order":["google-ai-studio/flex"]}'` halves its price, but Google AI Studio isn't among the providers that keep no data, so it also needs `DEBUTLY_ZERO_RETENTION=off`.
|
|
152
|
+
|
|
153
|
+
Models compared on the seeded-bug fixture (5 planted bugs, 3 agents), September 2026:
|
|
154
|
+
|
|
155
|
+
| Model | Bugs found (of 5) | Seconds per step | Cost |
|
|
156
|
+
|---|---|---|---|
|
|
157
|
+
| google/gemini-3.8-flash (flex tier) | 4 | 3.1 | $0.020 |
|
|
158
|
+
| z-ai/glm-5.3-flash | 4 | 3.8 | $0.004 |
|
|
159
|
+
| tencent/hy3 | 4 | 12.4 | $0.024 |
|
|
160
|
+
| qwen/qwen3.8-flash | 4 | 30.0 | $0.027 |
|
|
161
|
+
| qwen/qwen3.7-flash | 4 | 27.8 | $0.011 |
|
|
162
|
+
| inclusionai/ling-3.0-flash | 3 | 5.8 | $0.003 |
|
|
163
|
+
| bytedance-seed/seed-2.0-mini | 2 | 6.3 | $0.009 |
|
|
164
|
+
| xiaomi/mimo-v2.6-flash | 2 of 3 agents errored | 13.7 | $0.007 |
|
|
165
|
+
|
|
166
|
+
On a real SaaS app's nightly crew journey (2 owners, 4 teammates), GLM-5.3 Flash reached the same outcome and main finding as Gemini for $0.052 instead of $0.205, taking 224 steps instead of 128. DeepSeek V4 Flash caught the same fixture bugs as Gemini but averaged about 22 s a step, too slow to drive the agents in CI.
|
|
167
|
+
|
|
168
|
+
Compare models yourself (`model@endpoint` pins one OpenRouter provider endpoint):
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
node --env-file=.env --import tsx scripts/compare-models.ts z-ai/glm-5.3-flash google/gemini-3.8-flash@google-ai-studio/flex
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
`npx debutly costs --repo owner/app` shows your OpenRouter key's spend and what each app's latest nightly run cost.
|
|
175
|
+
|
|
176
|
+
## Development
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
git clone https://github.com/sroay/debutly.git && cd debutly && npm install
|
|
180
|
+
node bin/debutly.mjs --help # the debutly command, from source
|
|
181
|
+
npm test # includes the acceptance test: every seeded fixture bug must be caught
|
|
182
|
+
npm run typecheck
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
`fixture/` is a small app with seeded bugs that the acceptance test runs agents against.
|
|
186
|
+
|
|
187
|
+
## Contributing and security
|
|
188
|
+
|
|
189
|
+
Contributions are welcome: see [CONTRIBUTING.md](CONTRIBUTING.md). To report a vulnerability, see [SECURITY.md](SECURITY.md) rather than opening a public issue.
|
|
190
|
+
|
|
191
|
+
## License
|
|
192
|
+
|
|
193
|
+
[AGPL-3.0](LICENSE). You can use, modify and self-host Debutly freely. If you run a modified version as a service for others, you must publish your changes under the same licence.
|
package/bin/debutly.mjs
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// The `debutly` command. Debutly is TypeScript run through tsx, so there is no build step. Its
|
|
3
|
+
// own tsconfig is named, so the tsconfig of the app it runs in never changes how it compiles.
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { register } from "tsx/esm/api";
|
|
6
|
+
|
|
7
|
+
register({ tsconfig: fileURLToPath(new URL("../tsconfig.json", import.meta.url)) });
|
|
8
|
+
await import("../src/bin.ts");
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
CREATE TABLE "agents" (
|
|
2
|
+
"run_id" uuid NOT NULL,
|
|
3
|
+
"id" text NOT NULL,
|
|
4
|
+
"unit_id" text NOT NULL,
|
|
5
|
+
"name" text NOT NULL,
|
|
6
|
+
"role" text,
|
|
7
|
+
"inclusion" text,
|
|
8
|
+
"persona" jsonb NOT NULL,
|
|
9
|
+
CONSTRAINT "agents_run_id_id_pk" PRIMARY KEY("run_id","id")
|
|
10
|
+
);
|
|
11
|
+
--> statement-breakpoint
|
|
12
|
+
CREATE TABLE "customer_units" (
|
|
13
|
+
"run_id" uuid NOT NULL,
|
|
14
|
+
"id" text NOT NULL,
|
|
15
|
+
"kind" text NOT NULL,
|
|
16
|
+
"business" jsonb,
|
|
17
|
+
CONSTRAINT "customer_units_run_id_id_pk" PRIMARY KEY("run_id","id")
|
|
18
|
+
);
|
|
19
|
+
--> statement-breakpoint
|
|
20
|
+
CREATE TABLE "findings" (
|
|
21
|
+
"run_id" uuid NOT NULL,
|
|
22
|
+
"signature" text NOT NULL,
|
|
23
|
+
"kind" text NOT NULL,
|
|
24
|
+
"severity" text NOT NULL,
|
|
25
|
+
"confidence" text NOT NULL,
|
|
26
|
+
"title" text NOT NULL,
|
|
27
|
+
"detail" text NOT NULL,
|
|
28
|
+
"page_path" text NOT NULL,
|
|
29
|
+
"hit_by" text[] NOT NULL,
|
|
30
|
+
"visitors" integer NOT NULL,
|
|
31
|
+
"evidence" jsonb NOT NULL,
|
|
32
|
+
"sandbox_cause" text[],
|
|
33
|
+
CONSTRAINT "findings_run_id_signature_pk" PRIMARY KEY("run_id","signature")
|
|
34
|
+
);
|
|
35
|
+
--> statement-breakpoint
|
|
36
|
+
CREATE TABLE "runs" (
|
|
37
|
+
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
|
38
|
+
"target_url" text NOT NULL,
|
|
39
|
+
"goal" text NOT NULL,
|
|
40
|
+
"icp" text,
|
|
41
|
+
"tier" text,
|
|
42
|
+
"unit_kind" text,
|
|
43
|
+
"status" text DEFAULT 'queued' NOT NULL,
|
|
44
|
+
"model" text,
|
|
45
|
+
"estimate_low_usd" double precision,
|
|
46
|
+
"estimate_high_usd" double precision,
|
|
47
|
+
"cost_usd" double precision,
|
|
48
|
+
"input_tokens" integer,
|
|
49
|
+
"output_tokens" integer,
|
|
50
|
+
"report_md" text,
|
|
51
|
+
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
|
52
|
+
"started_at" timestamp with time zone,
|
|
53
|
+
"finished_at" timestamp with time zone
|
|
54
|
+
);
|
|
55
|
+
--> statement-breakpoint
|
|
56
|
+
CREATE TABLE "sessions" (
|
|
57
|
+
"run_id" uuid NOT NULL,
|
|
58
|
+
"agent_id" text NOT NULL,
|
|
59
|
+
"goal" text NOT NULL,
|
|
60
|
+
"outcome" text,
|
|
61
|
+
"outcome_note" text,
|
|
62
|
+
"input_tokens" integer,
|
|
63
|
+
"output_tokens" integer,
|
|
64
|
+
"cost_usd" double precision,
|
|
65
|
+
"started_at" timestamp with time zone DEFAULT now() NOT NULL,
|
|
66
|
+
"finished_at" timestamp with time zone,
|
|
67
|
+
CONSTRAINT "sessions_run_id_agent_id_pk" PRIMARY KEY("run_id","agent_id")
|
|
68
|
+
);
|
|
69
|
+
--> statement-breakpoint
|
|
70
|
+
CREATE TABLE "side_effects" (
|
|
71
|
+
"id" integer PRIMARY KEY GENERATED ALWAYS AS IDENTITY (sequence name "side_effects_id_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 START WITH 1 CACHE 1),
|
|
72
|
+
"run_id" uuid NOT NULL,
|
|
73
|
+
"outcome" text NOT NULL,
|
|
74
|
+
"rule" text,
|
|
75
|
+
"channel" text NOT NULL,
|
|
76
|
+
"host" text NOT NULL,
|
|
77
|
+
"url" text NOT NULL,
|
|
78
|
+
"recipient" text,
|
|
79
|
+
"summary" text,
|
|
80
|
+
"at" timestamp with time zone DEFAULT now() NOT NULL
|
|
81
|
+
);
|
|
82
|
+
--> statement-breakpoint
|
|
83
|
+
CREATE TABLE "steps" (
|
|
84
|
+
"run_id" uuid NOT NULL,
|
|
85
|
+
"agent_id" text NOT NULL,
|
|
86
|
+
"index" integer NOT NULL,
|
|
87
|
+
"url" text NOT NULL,
|
|
88
|
+
"title" text,
|
|
89
|
+
"action" jsonb NOT NULL,
|
|
90
|
+
"reasoning" text,
|
|
91
|
+
"observation" jsonb NOT NULL,
|
|
92
|
+
"signals" jsonb NOT NULL,
|
|
93
|
+
"error" text,
|
|
94
|
+
"blocked" text,
|
|
95
|
+
"screenshot_url" text,
|
|
96
|
+
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
|
97
|
+
CONSTRAINT "steps_run_id_agent_id_index_pk" PRIMARY KEY("run_id","agent_id","index")
|
|
98
|
+
);
|
|
99
|
+
--> statement-breakpoint
|
|
100
|
+
ALTER TABLE "agents" ADD CONSTRAINT "agents_run_id_runs_id_fk" FOREIGN KEY ("run_id") REFERENCES "public"."runs"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
101
|
+
ALTER TABLE "customer_units" ADD CONSTRAINT "customer_units_run_id_runs_id_fk" FOREIGN KEY ("run_id") REFERENCES "public"."runs"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
102
|
+
ALTER TABLE "findings" ADD CONSTRAINT "findings_run_id_runs_id_fk" FOREIGN KEY ("run_id") REFERENCES "public"."runs"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
103
|
+
ALTER TABLE "sessions" ADD CONSTRAINT "sessions_run_id_runs_id_fk" FOREIGN KEY ("run_id") REFERENCES "public"."runs"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
104
|
+
ALTER TABLE "side_effects" ADD CONSTRAINT "side_effects_run_id_runs_id_fk" FOREIGN KEY ("run_id") REFERENCES "public"."runs"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
105
|
+
ALTER TABLE "steps" ADD CONSTRAINT "steps_run_id_runs_id_fk" FOREIGN KEY ("run_id") REFERENCES "public"."runs"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
106
|
+
CREATE INDEX "runs_created_at_idx" ON "runs" USING btree ("created_at" DESC NULLS LAST);--> statement-breakpoint
|
|
107
|
+
CREATE INDEX "side_effects_run_idx" ON "side_effects" USING btree ("run_id");
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
CREATE TABLE "predictions" (
|
|
2
|
+
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
|
3
|
+
"run_id" uuid NOT NULL,
|
|
4
|
+
"metric" text NOT NULL,
|
|
5
|
+
"claim" text NOT NULL,
|
|
6
|
+
"predicted" jsonb NOT NULL,
|
|
7
|
+
"actual" jsonb,
|
|
8
|
+
"correct" boolean,
|
|
9
|
+
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
|
10
|
+
"checked_at" timestamp with time zone
|
|
11
|
+
);
|
|
12
|
+
--> statement-breakpoint
|
|
13
|
+
ALTER TABLE "predictions" ADD CONSTRAINT "predictions_run_id_runs_id_fk" FOREIGN KEY ("run_id") REFERENCES "public"."runs"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
14
|
+
CREATE INDEX "predictions_run_idx" ON "predictions" USING btree ("run_id");
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
CREATE TABLE "screenshots" (
|
|
2
|
+
"run_id" uuid NOT NULL,
|
|
3
|
+
"key" text NOT NULL,
|
|
4
|
+
"content_type" text NOT NULL,
|
|
5
|
+
"data" "bytea" NOT NULL,
|
|
6
|
+
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
|
7
|
+
CONSTRAINT "screenshots_run_id_key_pk" PRIMARY KEY("run_id","key")
|
|
8
|
+
);
|
|
9
|
+
--> statement-breakpoint
|
|
10
|
+
ALTER TABLE "runs" ADD COLUMN "app" text;--> statement-breakpoint
|
|
11
|
+
ALTER TABLE "runs" ADD COLUMN "trigger" text;--> statement-breakpoint
|
|
12
|
+
ALTER TABLE "runs" ADD COLUMN "ci_url" text;--> statement-breakpoint
|
|
13
|
+
ALTER TABLE "screenshots" ADD CONSTRAINT "screenshots_run_id_runs_id_fk" FOREIGN KEY ("run_id") REFERENCES "public"."runs"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
14
|
+
CREATE INDEX "screenshots_created_at_idx" ON "screenshots" USING btree ("created_at");--> statement-breakpoint
|
|
15
|
+
CREATE INDEX "runs_app_created_at_idx" ON "runs" USING btree ("app","created_at" DESC NULLS LAST);
|