@reallroboto/dfs
v0.1.0
Published
Agent-first CLI for the whole DataForSEO API, generated from the official OpenAPI spec, with a cost guard and a local store.
Maintainers
Readme
dataforseo-cli (dfs)
dfs: agent-first CLI for whole DataForSEO API, generated from official OpenAPI spec, with cost guard and local store. Status: in build. Catalog done (--help, --version, schema, search). Calls done: one HTTP exchange, Store save before print, Compact output, store show/list/path. Planner done: body validated before send (exit 3), --no-validate, --dry-run. Pricing core done: price tree from user_data (refreshed after 24 h), estimate, cost guard (exit 4; ceiling --max-cost, DFS_MAX_COST, $1 default). Price rules: every paid spec path has a rule or sits on the free list; LLM Responses (llm_responses) cost is unbounded, so it needs explicit --max-cost. Reuse done: same paid request within 12 h of a full success returns stored response at $0 (reused=<id> age=<age>); --fresh sends; free paths always sent. Transport done: free calls retry transient codes 4 times (1, 2, 4, 8 s + jitter); paid calls retry only when response shows cost 0; lost connection after paid send exits 1 (dfs +collect); 40103 never retried (remedy --fresh); pace: X-RateLimit-Remaining: 0 waits to next minute, ≤ 10 in flight per process, Live timeout 130 s. +run done: posts ≤ 100 tasks per post under one guard, saves post responses and task rows, polls most specific tasks_ready (5 s doubling to 30 s, --wait default 90 s), collects only own ids, last poll also unlisted ones (on_page via summary/{id} until crawl_progress = finished); timeout or --wait 0 exits 6 with pending ids. +collect done: one pass at root or one module, never posts; collects pending tasks through stored variant; recovers lost ids through id_list since last pass (first pass from Store creation; ai_optimization hand path warns when not served); 40403 → expired; id_list cost replaces task.cost only when non-zero. Release done: prepublishOnly gate (typecheck → lint → test → spec:check → build → pack check), publish.yml (tag v*, npm stage publish by OIDC, owner approves on npm), pnpm test:sandbox (Mac; 40404 file spec/sandbox-40404.json; time-bound example dates moved into vendor window, #26), pnpm fixtures:record. --page-all done: one task on a path with offset; offset to 10,000, then offset_token/search_after_token; one ceiling and one 9,000-character budget over all pages; stop before the page that passes the ceiling → exit 4 with rerun command (saved pages reuse at $0); --full one line per page. Store commands done: store search (FTS5 item_fts, diacritics folded, every word), list/search --since <n>m|h|d --path <words>, spend (non-sandbox task.cost, --by day|module|path|tag), sql (read-only connection), backup <file> (new file only, 600, one-step copy); paid calls write task rows at once (task_post: pending); schema contract user_version 6, full DDL in store.md (test-checked). Daily spec check done: ≤ 1 per 24 h, commits API with ETag, raw file at new SHA, structural check on overlaid copy, cache <config>/spec.json used when newer than snapshot; failure keeps spec, warns once, retries after 1 h; --version and store never fetch. Tests: dfs() helper marks check done unless { specCheck: true }. Skill done: skills/dfs/SKILL.md (git only, Story 58 rules); test resolves each dfs … command in Catalog. ADRs done: 0001–0008 in docs/adr/ (index linked below). Drift check done: pnpm spec:check (network) runs conditions 1–7 on newest master spec, job summary lists paths added/removed against snapshot; spec.yml weekly + dispatch, re-enables itself, forced failure on repo variable SPEC_CHECK_FORCE_FAIL=1. Exits done: combining rule in plain call too (40601, 40602, 20100 on a get = pending, exit 6); coverage checklist 1–4 and exits 0–6 each have a test.
- Package manager: pnpm. Node runs
.tsdirectly; testsnode --test(stack). - Checks:
pnpm typecheck && pnpm lint && pnpm test; thenpnpm build && pnpm pack:check.pnpm spec:snapshot(network) rewritesspec/snapshot.json; never edit it by hand.pnpm spec:check(network) = drift check, not part of Checks.pnpm test:sandbox,pnpm fixtures:record: Mac only, DataForSEO login, sandbox ($0). Release: runbook in workflows-release.md. - Spec: docs/spec/index.md. Start with overview.
- Docs bundle (OKF 0.2): docs/index.md. Decisions: ADR index.
Agent skills
| Topic | Rule | Detail |
|---|---|---|
| Issue tracker | GitHub issues via gh | docs/agents/issue-tracker.md |
| Triage labels | 5 canonical labels (string == role) | docs/agents/triage-labels.md |
| Domain docs | Single-context (GLOSSARY.md + docs/adr/) | docs/agents/domain.md |
