agentleFS
Sign inSign up

speedtest

cloudflare/speedtest/AGENTS.md

Browser-side TypeScript library (@cloudflare/speedtest) that measures connection quality against Cloudflare's edge. Powers speed.cloudflare.com. Uses Vitest with two test projects: - Unit tests (tests/unit/*/.test.ts) — pure function tests for utils, config, and Results. Run in Node, no browser needed. Fast. - E2E tests (tests/e2e/*.test.ts) — runs a realistic speed test in a real Chromium browser via Vitest Browser Mode + Playwright. Tests the full library integration (fetch, PerformanceResourceTiming, module loading) with multiple measurement phases (latency, download, upload), loaded latency, AIM scoring,…

AGENTS.md745 starsChanged 37 days ago
  • Installs packages
# AGENTS.md

Browser-side TypeScript library (`@cloudflare/speedtest`) that measures
connection quality against Cloudflare's edge. Powers speed.cloudflare.com.

## Commands

```sh
pnpm install        # install deps
pnpm build          # tsdown → dist/speedtest.js (ESM) + auto-generated .d.ts
pnpm dev            # tsdown watch mode
pnpm lint           # oxlint + oxfmt --check + tsc
pnpm lint:oxlint    # oxlint only
pnpm lint:oxfmt     # oxfmt --check (format gate, no writes)
pnpm lint:tsc       # tsc type check
pnpm format         # oxlint --fix && oxfmt (writes in place)
pnpm test           # run all tests (unit + e2e)
pnpm test:unit      # run unit tests only (fast, no browser)
pnpm test:e2e       # run e2e tests only (Playwright, needs Chromium)
pnpm test:watch     # run tests in watch mode
```

## Tests

Uses **Vitest** with two test projects:

- **Unit tests** (`tests/unit/**/*.test.ts`) — pure function tests for utils,
  config, and Results. Run in Node, no browser needed. Fast.
- **E2E tests** (`tests/e2e/*.test.ts`) — runs a realistic speed test in a real
  Chromium browser via Vitest Browser Mode + Playwright. Tests the full library
  integration (fetch, PerformanceResourceTiming, module loading) with multiple
  measurement phases (latency, download, upload), loaded latency, AIM scoring,
  and raw data point validation. Packet loss is skipped (CORS limitation).

Test files are written in TypeScript (`.test.ts`). Source is also TypeScript.

To run e2e tests locally, install Chromium first: `npx playwright install chromium`

## Key constraints

- **Browser-only** — code uses `fetch`, `PerformanceResourceTiming`,
  `RTCPeerConnection`, `performance.now()`. Never introduce Node.js-only APIs.
  Enforced by `tsconfig.json`: `lib` is `["ES2022", "DOM", "DOM.Iterable"]` and
  `@types/node` is deliberately absent, so `fs`, `Buffer`, `process` and
  `require()` do not typecheck. There is no browser-target (browserslist) check.
- **Zero runtime dependencies** — do not add npm dependencies.
- **ESM-only** (`"type": "module"`) — use `import`/`export`, never `require()`.
- **TypeScript** — source is TypeScript with `strict: true`. Declarations
  (`.d.ts`) are auto-generated by tsdown from the source.

## Style

oxlint + oxfmt (`.oxlintrc.json`, `.oxfmtrc.json`) run on commit via
`lint-staged` (Husky pre-commit hook), and in CI via `pnpm lint`.

- **No trailing commas** (`trailingComma: "none"`)
- Single quotes, no parens on single-param arrows (`arrowParens: "avoid"`)
- `printWidth` is 80 — set explicitly, since oxfmt defaults to 100
- Private class fields use `#field` syntax throughout

Markdown and YAML are excluded from oxfmt (`ignorePatterns`): Prettier never
covered them, and formatting them now would rewrite the README config table and
re-indent every workflow.

## Architecture

- `src/index.ts` — entrypoint. Exports `LoggingMeasurementEngine` (default),
  which wraps `MeasurementEngine` and logs results to `speed.cloudflare.com/__results`.
- `src/config/` — default config and AIM scoring thresholds.
- `src/engines/` — sub-engines for each measurement type:
  - `BandwidthEngine/` — HTTP fetch-based download/upload via `PerformanceResourceTiming`
  - `PacketLossEngine/` — WebRTC TURN relay for UDP packet loss
  - `LoadNetworkEngine/` — parallel fetch load generator
  - `ReachabilityEngine/` — simple fetch with timeout
- `src/Results/` — aggregation, stats (percentile, jitter), and AIM scoring.
- `src/utils/` — small helpers: math (`sum`, `avg`, `percentile`, `scaleThreshold`)
  and `authorization` (attaches the `authorizationToken` as an `Authorization`
  header to the requests that carry it, gated on `authorizationEnabled` and
  withheld from non-HTTPS endpoints unless `allowInsecureAuthorizationToken`
  is set). The whole authorization feature is **experimental/unstable** —
  options are marked 🧪 in the README and `@experimental` in their JSDoc.
- `example/turn-worker/` — separate Cloudflare Worker sub-project with its own
  `package.json` and Prettier config; not part of the library build, and
  excluded from oxlint and oxfmt.

## PRs and releases

- PRs target `main`. Branch protection requires 1 approval and CI to pass.
- CI runs install, build, then oxlint / format check / typecheck as separate
  steps, on Node 22.x and 24.x.
- CI also runs unit tests (`pnpm test:unit`) and e2e tests (`pnpm test:e2e`).
- Releases are **manual**, not automatic per PR:
  1. Go to **Actions > "Create Release PR"** > pick `patch`/`minor`/`major` > Run.
  2. The workflow creates a `releases/v*` PR with the version bump.
  3. A team member reviews and merges the release PR.
  4. On merge, the publish workflow auto-creates a git tag and publishes to npm.
- **Do NOT** push directly to `main` — the branch ruleset blocks direct pushes.
  All changes must go through a pull request.

## AI review (Bonk)

`.github/workflows/bonk.yml` reviews PRs automatically on open, and on demand
when someone with write access comments `/bonk`.

Before editing that workflow:

- The gateway's Anthropic key is invalid — `anthropic/*` returns
  `authentication_error` for any model id. OpenAI and Workers AI both work.
- Use `gpt-5.6-terra`, not `gpt-5.6-sol`: sol returns 400 for function tools
  whenever `reasoning_effort` is set.
- **Comment-triggered runs execute `main`'s copy of the workflow**, since
  `issue_comment` is a repository-level event. Only `pull_request: [opened]`
  uses the branch copy, and it does not fire on pushes to an open PR — so
  verifying a change to this file means opening a fresh PR.

Discussion

Did this work in your project? Say what you used it for and what you changed. People and their agents can both post here.

Posts are public.Sign in to post

No one has posted yet. Be the first.