mirror of
https://github.com/jackwener/OpenCLI.git
synced 2026-09-14 18:25:42 +08:00
0a85e73aa5
* feat(convention): listing↔detail id pairing rule + CI gate Adds a hard convention: when a site exposes both a listing-class command (search / hot / top / recent / ...) and a detail-class command (read / paper / article / view / ...), every listing row MUST surface an id-shaped column whose value round-trips into the detail command. Without that, an agent has no way to follow up on a listing row except re-searching by title or scraping URLs out of band — both of which break the agent-native contract. What's in this PR - docs/conventions/listing-detail-id-pairing.md — full rule, examples table, why-it-matters, what counts as id-shaped, exemption taxonomy, how to add an id column to a listing. - scripts/check-listing-id-pairing.mjs — validator that reads cli-manifest.json, classifies each entry as listing / detail / other, and fails when a listing on a site that also has a read-detail command is missing an id-shaped column. Exemption allowlist records WHY each pair is exempt so future maintainers know what to verify. - npm run check:listing-id-pairing — strict-mode wrapper. - CI: new step in build job runs the validator after the manifest freshness check on Linux. - docs/developer/ts-adapter.md — cross-link from the adapter authoring guide. - docs/.vitepress/config.mts — sidebar entries for the new conventions section. Fixes brought to zero violations - 1688/search: add offer_id (already extracted, just surfaced) - bluesky/user: add uri (AT URI round-trips into bluesky/thread) - tieba/search: add id + url (thread_id already extracted) - tieba/hot: add url (rows are topics, not threads — url is the best-effort round-trip handle, doc'd as such) Exemptions (intentional, doc'd in EXEMPT map with rationale) - nowcoder/hot, bluesky/trending, twitter/trending — listing rows are topic strings, not posts. - lesswrong/user, reddit/user — rows are profile-attribute key/value pairs, addressed by the username arg. - discord-app/search — desktop UI session, message ids not extractable. - notion/search — Strategy.UI Quick Find, page ids not exposed in DOM. Validator output after this PR: 32 sites scanned, 75 listings checked, 7 exempted, 0 violations. * fix(convention): tighten listing id gate * fix(convention): close url-derived id loophole
100 lines
3.3 KiB
JSON
100 lines
3.3 KiB
JSON
{
|
|
"name": "@jackwener/opencli",
|
|
"version": "1.7.11",
|
|
"publishConfig": {
|
|
"access": "public"
|
|
},
|
|
"description": "Make any website or Electron App your CLI. AI-powered.",
|
|
"engines": {
|
|
"node": ">=21.0.0"
|
|
},
|
|
"type": "module",
|
|
"main": "dist/src/main.js",
|
|
"bin": {
|
|
"opencli": "dist/src/main.js"
|
|
},
|
|
"exports": {
|
|
".": "./dist/src/main.js",
|
|
"./registry": "./dist/src/registry-api.js",
|
|
"./errors": "./dist/src/errors.js",
|
|
"./types": "./dist/src/types.js",
|
|
"./utils": "./dist/src/utils.js",
|
|
"./logger": "./dist/src/logger.js",
|
|
"./launcher": "./dist/src/launcher.js",
|
|
"./browser/cdp": "./dist/src/browser/cdp.js",
|
|
"./browser/page": "./dist/src/browser/page.js",
|
|
"./browser/utils": "./dist/src/browser/utils.js",
|
|
"./download": "./dist/src/download/index.js",
|
|
"./download/article-download": "./dist/src/download/article-download.js",
|
|
"./download/media-download": "./dist/src/download/media-download.js",
|
|
"./download/progress": "./dist/src/download/progress.js",
|
|
"./pipeline": "./dist/src/pipeline/index.js"
|
|
},
|
|
"files": [
|
|
"dist/src/",
|
|
"clis/",
|
|
"cli-manifest.json",
|
|
"scripts/",
|
|
"README.md",
|
|
"LICENSE"
|
|
],
|
|
"scripts": {
|
|
"dev": "tsx src/main.ts",
|
|
"dev:bun": "bun src/main.ts",
|
|
"build": "npm run clean-dist && tsc && npm run copy-yaml && npm run build-manifest",
|
|
"build-manifest": "tsx src/build-manifest.ts",
|
|
"clean-dist": "node scripts/clean-dist.cjs",
|
|
"copy-yaml": "node scripts/copy-yaml.cjs",
|
|
"start": "node dist/src/main.js",
|
|
"start:bun": "bun dist/src/main.js",
|
|
"preuninstall": "node -e \"fetch('http://127.0.0.1:'+(process.env.OPENCLI_DAEMON_PORT||'19825')+'/shutdown',{method:'POST',headers:{'X-OpenCLI':'1'},signal:AbortSignal.timeout(3000)}).catch(()=>{})\" || true",
|
|
"postinstall": "node scripts/postinstall.js || true; node scripts/fetch-adapters.js || true",
|
|
"typecheck": "tsc --noEmit",
|
|
"prepare": "[ -d src ] && npm run build || true",
|
|
"prepublishOnly": "npm run build",
|
|
"test": "vitest run --project unit --project extension --project adapter",
|
|
"test:bun": "bun vitest run --project unit --project extension --project adapter",
|
|
"test:adapter": "vitest run --project adapter",
|
|
"test:all": "vitest run",
|
|
"test:e2e": "vitest run --project e2e",
|
|
"check:listing-id-pairing": "node scripts/check-listing-id-pairing.mjs --strict",
|
|
"docs:dev": "vitepress dev docs",
|
|
"docs:build": "vitepress build docs",
|
|
"docs:preview": "vitepress preview docs"
|
|
},
|
|
"keywords": [
|
|
"cli",
|
|
"browser",
|
|
"web",
|
|
"ai"
|
|
],
|
|
"author": "jackwener",
|
|
"license": "Apache-2.0",
|
|
"repository": {
|
|
"type": "git",
|
|
"url": "git+https://github.com/jackwener/opencli.git"
|
|
},
|
|
"dependencies": {
|
|
"@mozilla/readability": "^0.6.0",
|
|
"cli-table3": "^0.6.5",
|
|
"commander": "^14.0.3",
|
|
"js-yaml": "^4.1.0",
|
|
"turndown": "^7.2.2",
|
|
"turndown-plugin-gfm": "^1.0.2",
|
|
"undici": "^8.0.2",
|
|
"ws": "^8.18.0"
|
|
},
|
|
"devDependencies": {
|
|
"@types/jsdom": "^27.0.0",
|
|
"@types/js-yaml": "^4.0.9",
|
|
"@types/node": "^25.5.2",
|
|
"@types/turndown": "^5.0.6",
|
|
"@types/ws": "^8.5.13",
|
|
"jsdom": "^29.0.2",
|
|
"tsx": "^4.19.3",
|
|
"typescript": "^6.0.2",
|
|
"vitepress": "^1.6.4",
|
|
"vitest": "^4.1.0"
|
|
}
|
|
}
|