* refactor: consolidate 6 skills into 3, remove mechanical commands Replaces opencli-oneshot / opencli-explorer / opencli-browser / opencli-usage with a single opencli-adapter-author skill that takes the AI agent end-to-end: site recon, API discovery, field decoding, adapter coding, and `opencli browser verify`. Removes the mechanical commands (`explore`, `synthesize`, `generate`, `cascade`, `record`) and their src/tests — they were codegen scaffolding meant for agents, which the new skill handles more flexibly via `opencli browser` primitives. Skill highlights: - Top-level decision tree + 12-step runbook - 5 site patterns (SPA / SSR / JSONP / Token / Streaming) - 5-layer API discovery (network → initial state → bundle → token → interceptor) - Field decode playbook (self-explanatory → codes → sort-key comparison) - Output design guide (columns, types, order, ≤15 per adapter) - Two-layer site memory: in-repo seeds for eastmoney/xueqiu/bilibili/tonghuashun plus local `~/.opencli/sites/<site>/` runtime workspace Kept skills: opencli-autofix (now points to adapter-author for rewrites), smart-search. Kept primitives: `browser *`, `doctor`, `list`, `validate`, `verify`, `<site> <cmd>`, `plugin *`, `completion`. No backward compatibility shims. Full test suite (1605 tests) passes. * review fixes: honest coverage, hard memory-hit path, typo, stale docs - site-memory hit path no longer jumps to writing adapter; forces Step 5 endpoint re-verification + Step 7 field check, and 30-day expiry - site-memory.md now specifies exact schemas for endpoints.json / field-map.json / notes.md / fixtures + write-back timing rules - coverage-matrix.md marks unverified patterns as 🟡 with an evidence section citing coingecko dry run + PR #1091 eastmoney + bilibili - eastmoney seed typo: resolveSecids -> resolveSecid (and splitSymbols) - docs/developer/ai-workflow.md rewritten to teach the adapter-author skill + opencli browser * primitives (dropped generate/synthesize/ cascade/explore references) - ts-adapter.md, getting-started.md, CHANGELOG.md:87 updated to point at opencli-adapter-author * fix(ci): resync package-lock + drop stale built-in list reference - Regenerate package-lock.json to restore @emnapi/core + @emnapi/runtime entries that got dropped during the rebase — `npm ci` was failing on all CI jobs (build / audit / docs-build / bun-test / unit-test) - docs/guide/getting-started.md: built-in list dropped `explore`, now reads (list, validate, verify, browser, doctor, plugin...) * fix(ci): restore package-lock.json from main (unrelated lockfile churn)
3.4 KiB
TypeScript Adapter Guide
Use TypeScript adapters when you need browser-side logic, multi-step flows, DOM manipulation, or complex data extraction that goes beyond simple API fetching.
Basic Structure
import { cli, Strategy } from '@jackwener/opencli/registry';
import { CommandExecutionError, EmptyResultError } from '@jackwener/opencli/errors';
cli({
site: 'mysite',
name: 'search',
description: 'Search MySite',
domain: 'www.mysite.com',
strategy: Strategy.COOKIE, // PUBLIC | COOKIE | HEADER
args: [
{ name: 'query', required: true, help: 'Search query' },
{ name: 'limit', type: 'int', default: 10, help: 'Max results' },
],
columns: ['title', 'url', 'date'],
func: async (page, kwargs) => {
const { query, limit = 10 } = kwargs;
// Navigate and extract data
await page.goto('https://www.mysite.com');
const data = await page.evaluate(`
(async () => {
const res = await fetch('/api/search?q=${encodeURIComponent(String(query))}', {
credentials: 'include'
});
return (await res.json()).results;
})()
`);
if (!Array.isArray(data)) throw new CommandExecutionError('MySite returned an unexpected response');
if (!data.length) throw new EmptyResultError('mysite search', 'Try a different keyword');
return data.slice(0, Number(limit)).map((item: any) => ({
title: item.title,
url: item.url,
date: item.created_at,
}));
},
});
Strategy Types
| Strategy | Constant | Use Case |
|---|---|---|
| Public | Strategy.PUBLIC |
No auth needed |
| Cookie | Strategy.COOKIE |
Browser session cookies |
| Header | Strategy.HEADER |
Custom headers/tokens |
The page Object
The page parameter provides browser interaction methods:
page.goto(url)— Navigate to a URLpage.evaluate(script)— Execute JavaScript in the page contextpage.waitForSelector(selector)— Wait for an elementpage.click(selector)— Click an elementpage.type(selector, text)— Type text into an input
The kwargs Object
Contains parsed CLI arguments as key-value pairs. Always destructure with defaults:
const { query, limit = 10, format = 'json' } = kwargs;
For most search/read/detail commands, the main subject should be positional (opencli mysite search "rust", opencli mysite article 123) instead of a named flag such as --query or --id. Keep named flags for optional modifiers.
Error Handling
Prefer throwing CliError subclasses from src/errors.ts for expected adapter failures:
AuthRequiredErrorfor missing login / cookiesEmptyResultErrorfor empty but valid responsesCommandExecutionErrorfor unexpected API or browser failuresTimeoutErrorfor site timeoutsArgumentErrorfor invalid user input
Avoid raw Error for normal adapter control flow. This keeps top-level CLI output consistent and preserves hints for users.
AI-Assisted Development
Use the opencli-adapter-author skill plus the opencli browser * primitives to scaffold and verify adapters end-to-end:
# Recon on the target site
opencli browser open https://example.com
opencli browser network
opencli browser state
# Scaffold + verify
opencli browser init mysite/trending
opencli browser verify mysite/trending
See AI Workflow for the full loop and the adapter-author skill for the step-by-step runbook.