Commit Graph

753 Commits

Author SHA1 Message Date
jackwener b2a0a7a961 refactor: remove version field from GenerateOutcome and EarlyHint
All consumers are in the same repo and evolve together — version field
adds ceremony without practical value at this stage.

Keeps schema_version in VerifiedArtifactMetadata (sidecar file format).
2026-04-08 21:16:06 +08:00
jakevin 1662e9a73c refactor: rename operate to browser (#883)
* refactor: rename operate to browser

* fix: preserve browser rename compatibility

* fix: bump generate outcome schema version

* fix: keep generate outcome schema at v1
2026-04-08 21:03:57 +08:00
jakevin 991c8ce944 feat: P2 EarlyHint callback channel for cost gating (#882)
* fix: use Strategy.PUBLIC enum in skill-generate test to fix typecheck regression

* feat: add P2 EarlyHint callback channel to generateVerifiedFromUrl

Add optional onEarlyHint callback for internal cost gating before verify stage.

- EarlyHint type: version, stage, continue, reason, confidence, candidate?
- 3 emit points: explore (viable/not), synthesize (candidate/not), cascade (auth/ok)
- candidate only on synthesize/cascade + continue:true (not on stop or explore)
- unsupported-required-args goes directly to P1 terminal, no P2 hint emitted
- 6 new tests covering all hint paths + guardrails
2026-04-08 19:51:05 +08:00
jakevin 9365afc05f fix: use Strategy.PUBLIC enum in skill-generate test (#881) 2026-04-08 19:36:05 +08:00
jakevin 7ad8c1c42a feat: opencli-generate skill spec + thin wrapper (#880)
* docs: add opencli-generate skill spec (SKILL.md)

Captures A+B consensus from team discussion:
- Input: url + goal? (natural language intent hint)
- Output: SkillOutput with machine-readable fields + human message
- Decision tree: thin mapping from GenerateOutcome
- Guardrails: no re-orchestration, no auto-escalation, no new taxonomy
- P1/P2 boundary: P1 is single source of truth, P2 transparent to skill

* fix: address review nits on skill spec

- Make path explicitly optional in needs-human-check decision tree
- Add missing non-array-result message template

* feat: add GenerateOutcome → SkillOutput thin wrapper

Implements the skill mapping layer per opencli-generate SKILL.md:
- mapOutcomeToSkillOutput: thin translation from P1 contract to agent-facing output
- executeGenerateSkill: entry point accepting SkillInput (url + goal?)
- Message templates for all StopReason and EscalationReason values
- 8 tests covering all outcome paths and contract shape validation

* fix: prefer outcome.message for richer context in needs-human-check

When GenerateOutcome has a message (e.g. "required args: id"), use it
instead of the generic template, so the specific args info reaches the user.
2026-04-08 19:28:16 +08:00
VegetableDog cb34aa1009 fix(docs): add missing .md extension to adapter index links (#874)
All 68 browser adapter links and 8 desktop adapter links in
docs/adapters/index.md were missing the .md file extension,
causing broken links when navigating the documentation on GitHub.
2026-04-08 19:25:43 +08:00
jakevin 05e1b939a5 test: make verified path assertions cross-platform (#879) 2026-04-08 19:09:12 +08:00
jakevin 6ef55e85e9 chore: release v1.6.9 (#875) 2026-04-08 19:06:32 +08:00
jakevin bc82450311 feat: verified generate pipeline with structured contract (#878)
* feat: add verified generate pipeline

* Refine verified generate v1 flow

* Tighten verified generate v1 contract

* upgrade GenerateOutcome contract: structured taxonomy + sidecar metadata

Contract changes per team consensus (5 design principles):

1. Rename BlockReason taxonomy by skill decision needs:
   - no-api-discovered → no-viable-api-surface
   - auth-required → auth-too-complex
   - browser-unavailable → execution-environment-unavailable

2. Add stage + confidence to all blocked outcomes so skill knows
   where it stopped and how sure the system is.

3. Replace flat candidate/issue in needs-human-check with structured
   EscalationContext: stage, reason, confidence, suggested_action,
   candidate with explicit reusable + reusability_reason.

4. Add sidecar metadata (.meta.json) for verified artifacts —
   separates product/provenance contract from executable YAML.

5. Export shared decision language types (Stage, Confidence,
   StopReason, EscalationReason, SuggestedAction, ReusabilityKind)
   for future early-hint contract consistency.

* fix: make reusability contract explicit and self-consistent

Addresses @First-principles-0 review:

1. Add reusable + reusability_reason to VerifiedAdapter so success
   outcome is self-contained — skill doesn't need to read sidecar
   metadata or assume success implies reusable.

2. Rename 'candidate-yaml' → 'unverified-candidate' to resolve
   semantic clash with reusable: false. Now the pairing is always
   consistent:
   - reusable: true  + verified-artifact (success)
   - reusable: true  + unverified-candidate (candidate usable with manual args)
   - reusable: false + unverified-candidate (verify failed, candidate exists)
   - reusable: false + not-reusable (nothing worth keeping)

* refactor: merge reusable + reusability_reason into single reusability enum

Removes dual-truth contract (boolean + string) in favor of a single
Reusability enum ('verified-artifact' | 'unverified-candidate' | 'not-reusable').

- VerifiedAdapter.reusability replaces .reusable + .reusability_reason
- EscalationContext.candidate.reusability replaces .reusable + .reusability_reason
- Top-level GenerateOutcome.reusability present on all success and needs-human-check outcomes
- Sidecar metadata (.meta.json) retains reusable + reusability_reason for external compat
- Updated all 7 tests to assert single reusability field
2026-04-08 18:57:31 +08:00
jakevin 276ab8b8bf chore: bump version to 1.6.9 (#876) v1.6.9 2026-04-08 16:03:35 +08:00
jakevin 85d73b5b83 refactor(doctor/status): unify daemon health checks into getDaemonHealth() (#873)
- Add getDaemonHealth() returning 'stopped' | 'no-extension' | 'ready'
- Delete discover.ts (thin wrapper with no value)
- Bridge uses getDaemonHealth() + _pollUntilReady() (eliminates duplicate polling)
- Doctor simplified: live check auto-starts daemon; no-live mode does minimal
  auto-start only when stopped (avoids misreporting idle-exit as failure)
- CommanderAdapter preserves error message/hint detail (not just generic title)
- All callers use single unified status entry point
2026-04-08 15:53:40 +08:00
AstroHan 79fb0822fc fix(test): repair binance pipeline imports (#870) 2026-04-08 14:30:35 +08:00
Yohan fd116fe4bc fix(xiaohongshu): scope note interaction selectors to .interact-container (#839)
* fix(xiaohongshu): scope note interaction selectors to .interact-container

The .like-wrapper / .collect-wrapper / .chat-wrapper class names are
also used by every comment's like/reply buttons in the comment section.
querySelector returned the FIRST match — which on a note with comments
is a comment's count, not the post's. As a result, `xiaohongshu note`
returned wrong like/collect/comment counts for any note that had user
comments.

Scoping each selector to .interact-container (the post's main
interaction bar) returns the correct post-level counts.

Verified on multiple notes:
- Note A: was returning likes=2, now correctly returns likes=74
- Note B: was returning likes=1, now correctly returns likes=796
- Note C: was returning likes=1, now correctly returns likes=269

* test(xiaohongshu): add regression check for .interact-container selector scope

Verify the evaluate script passes scoped selectors so unscoped
versions can't silently regress. Follows reviewer suggestion to
assert on page.evaluate.mock.calls[0][0].

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 14:18:44 +08:00
jakevin ea8b1a567b fix(browser): make bridge and doctor reflect real connection state (#871) 2026-04-08 14:11:01 +08:00
sline a3eb2dc90a feat: add GitHub Trending, Binance, and Weather adapters (24 commands) (#214)
* feat: add GitHub Trending, Binance, and Weather (Open Meteo) adapters

GitHub Trending (2 commands, browser mode):
- repos: trending repositories with stars, forks, language filter
- developers: trending developers with popular repos
  Supports --since daily/weekly/monthly and --language filter

Binance (11 commands, public API via data-api.binance.vision):
- top: top trading pairs by 24h volume
- price: single pair 24h price stats
- prices: latest prices for all pairs
- ticker: 24h ticker statistics
- gainers: top gaining pairs by 24h change
- losers: top losing pairs by 24h change
- trades: recent trades for a pair
- depth: order book bid prices
- asks: order book ask prices
- klines: candlestick/kline data
- pairs: list active trading pairs

Weather / Open Meteo (11 commands, free public API, no key needed):
- current: current weather for a city
- forecast: daily forecast up to 16 days
- hourly: hourly forecast
- search: city geocoding lookup
- air: air quality index (simple)
- air-quality: detailed air quality (US/EU AQI, PM2.5, PM10, ozone, NO2, SO2)
- sunrise: sunrise/sunset times with UV index
- wind: detailed wind forecast with gusts and 80m altitude
- precipitation: rain/snow forecast with probability
- history: historical weather up to 92 past days
- compare: side-by-side weather comparison across cities

All 24 commands tested with live data. 258 existing tests pass.

* docs: add missing douban, sinablog, substack adapter documentation

* fix(binance): sort numeric metrics and filter active pairs

* chore: drop non-binance adapters from pr214

* chore: drop binance docs from pr214

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-04-08 01:08:00 +08:00
X 61b247f90c feat(quark): add Quark Drive adapter (#858)
* feat(quark): add Quark Drive adapter (ls, mkdir, mv, rename, rm, save, share-tree)

Browser-based adapter for Quark Cloud Drive (pan.quark.cn) using cookie
strategy. Supports file browsing, folder management, and saving shared
files with task polling for async operations.

* fix(quark): address review feedback on adapter correctness and docs

- ls: fix depth off-by-one (default 0 now lists target folder only)
- save/mv: report success only after pollTask confirms completion; throw on timeout
- save/mv: reject combining --to and --to-fid instead of silently preferring --to-fid
- utils: check content-type before calling r.json() to handle non-JSON responses gracefully
- tests: add quark graceful auth-failure E2E cases for all 7 commands
- docs: add Browser Bridge extension to prerequisites; fix mkdir --parent example; expand command table with positional args; add Notes section explaining stoken flow

* fix(quark): map auth failures and cover utils

* fix(quark): reuse auth mapping for share-tree

---------

Co-authored-by: xzy <xzy@mbp-m5.local>
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-04-08 00:28:59 +08:00
AstroHan ce559da7fc feat(zhihu): add interaction commands (#868)
* feat(zhihu): add interaction commands

* fix(zhihu): tighten interaction target anchoring

* fix(zhihu): scope comment authorship proof

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-04-07 23:17:51 +08:00
jakevin 56d15d186b feat: Self-Repair protocol for automatic adapter fixing (#866)
* feat: add Self-Repair protocol for automatic adapter fixing

When an AI agent uses opencli and a command fails, the agent
automatically diagnoses the failure, fixes the adapter, and retries.

- Add CLAUDE.md with Self-Repair protocol (auto-loaded by Claude Code)
- Add designs/self-repair-protocol.md documenting the approach
- Update opencli-repair skill: add Safety Boundaries (AUTH/BROWSER → STOP,
  sourcePath-only scope, max 3 rounds), fix AUTH_REQUIRED guidance
- Update opencli-usage skill: add Self-Repair section

Key design decisions:
- Repair target is always RepairContext.adapter.sourcePath (works for both
  repo-local clis/ and user-local ~/.opencli/clis/)
- Only adapter files may be modified, never core src/
- Max 3 repair rounds per failure
- AUTH_REQUIRED and BROWSER_CONNECT are hard stops (report, don't modify)

* fix: align auth boundary and scope language across all documents

- Remove "Auth changed (AUTH_REQUIRED)" exploration section from
  opencli-repair skill — contradicted the hard stop rule above it
- Update design doc: scope language matches repo-local + explicit skill
  delivery model, not universal product behavior
- Update usage skill: reference sourcePath instead of "files under clis/"

* fix: replace remaining repo-relative clis/ paths with sourcePath in design doc

* refactor: rename opencli-repair to opencli-autofix, remove CLAUDE.md

CLAUDE.md was wrong — users don't work inside the opencli repo, and
the protocol shouldn't assume Claude Code. The skill is the portable
delivery mechanism for any AI agent.

- Rename skills/opencli-repair → skills/opencli-autofix
- Remove CLAUDE.md (not the right delivery mechanism)
- Update all references in usage skill and design doc
- Design doc rewritten to reflect skill-first approach

* fix: use sourcePath in example repair session

* feat: emit AutoFix hint on repairable adapter errors

When a command fails with a repairable error (SELECTOR, EMPTY_RESULT,
COMMAND_EXEC, or generic http/not-found), the error output now includes
a hint telling agents to re-run with OPENCLI_DIAGNOSTIC=1 for repair
context. This is the trigger mechanism that bridges the gap between
"command failed" and "agent enters autofix loop".

Non-repairable errors (AUTH_REQUIRED, BROWSER_CONNECT, ARGUMENT) do not
emit the hint — these require user action, not adapter fixes.

* fix: narrow AutoFix hint to adapter-drift errors only

Remove hint from CommandExecutionError (covers env/launcher/runtime
issues, not adapter drift) and generic http errors (often temporary
site issues). Keep hint only for SelectorError, EmptyResultError,
and generic not-found — clear adapter-drift signals.
2026-04-07 23:00:03 +08:00
jakevin 57d59d5e01 fix: graceful fallback when extension lacks network-capture support (#865)
When the Browser Bridge extension is older than the CLI, sending
'network-capture-start' to the daemon returns 'Unknown action',
causing explore and operate-open to crash with an unhandled error.

Wrap startNetworkCapture calls with .catch() so they degrade
gracefully — explore continues without network capture data, and
operate-open falls back to the JS interceptor injection.
2026-04-07 20:42:14 +08:00
Kyrie Cai f6c13ef159 fix plugin host root resolution (#852)
Co-authored-by: Kyrie <kyrie@mallab.world>
2026-04-07 20:32:08 +08:00
GanFanNewOrder 9c5571eba3 feat(jianyu): add search adapter for bid notices (#849)
* feat(jianyu): add search adapter for bid notices

* docs(jianyu): add adapter usage guide

* docs(jianyu): neutralize examples and add adapter guide

---------

Co-authored-by: 泽加武 <zejiawu@zejiawudeMac-mini.local>
2026-04-07 19:20:00 +08:00
jakevin 813e282356 fix(twitter): relax reply composer textarea timeout from 8s to 15s (#862)
The compose page needs to load Draft.js editor which is heavier than
primaryColumn. 8s is too tight for slow networks and will cause flaky
failures. 15s aligns with the file input timeout (20s) in magnitude.
2026-04-07 18:50:39 +08:00
陈家名 4ea8f7e8c8 fix(twitter): use composer for text replies (#860)
Co-authored-by: 陈家名 <chenjiaming@kezaihui.com>
2026-04-07 18:08:14 +08:00
dependabot[bot] d85681e1cc chore(deps): bump @types/node from 22.19.15 to 25.5.2 (#838)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.19.15 to 25.5.2.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 25.5.2
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-07 14:42:16 +08:00
dependabot[bot] f7e7a37d8f chore(deps): bump vitest from 4.1.1 to 4.1.2 (#835)
Bumps [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest) from 4.1.1 to 4.1.2.
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.2/packages/vitest)

---
updated-dependencies:
- dependency-name: vitest
  dependency-version: 4.1.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-07 14:42:04 +08:00
dependabot[bot] 1e3904ba3c chore(deps): bump undici from 7.24.6 to 8.0.2 (#837)
Bumps [undici](https://github.com/nodejs/undici) from 7.24.6 to 8.0.2.
- [Release notes](https://github.com/nodejs/undici/releases)
- [Commits](https://github.com/nodejs/undici/compare/v7.24.6...v8.0.2)

---
updated-dependencies:
- dependency-name: undici
  dependency-version: 8.0.2
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-07 14:41:55 +08:00
AstroHan b8f0f583ef fix: include intercepted payloads in diagnostic (#829)
* fix: include intercepted payloads in diagnostic

* refactor: isolate captured payloads in diagnostic

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-04-06 15:20:34 +08:00
AstroHan 1cd0b4b404 fix: correct misleading behaviors in engine, fix, and generate (#826)
- engine.ts: replace `git add -A` with scope-aware `execFileSync` to
  stage only files matching config.scope globs, and guard against empty
  scope degenerating into staging all files
- fix.ts: pass prompt via stdin `input` option instead of shell string
  interpolation to prevent $, backtick, and other metacharacter expansion
- generate.ts: update stale comment that claimed unimplemented pipeline
  steps (register, verify, Strategy Cascade)
2026-04-06 15:05:29 +08:00
jakevin 60c92e1150 chore: bump version to 1.6.8 (#825) v1.6.8 2026-04-06 03:24:52 +08:00
jakevin 009c25b955 refactor: remove scoring heuristic, use noise filter + structured metadata (#824)
* refactor: remove scoring heuristic, replace with noise filter + metadata

The scoring mechanism was a pre-LLM heuristic that compressed rich endpoint
metadata into a single number. Since this project is designed for AI Agents,
the agent can reason about structured metadata directly.

Changes:
- Remove scoreEndpoint/scoreRequest/scoreWriteRequest and all score fields
- Replace with isNoiseUrl() filter (tracking/beacon/pixel) + isUsefulEndpoint()
- Remove artificial confidence percentages (was score/20)
- Sort by itemCount (transparent, observable) instead of weighted score
- Endpoints now expose full structured metadata for agent consumption
- Net reduction: -43 lines

* fix: widen endpoint filter to keep single-object JSON and stats/metric URLs

- Remove stats/metric from noise pattern — these are often business APIs
- Relax isUsefulEndpoint to keep any JSON endpoint, not just arrays
  (preserves /me, /profile, /detail and other single-object APIs)

* fix: add deterministic endpoint ordering for generate/synthesize path

The AI agent path doesn't need ranking, but generate/synthesize still
pick candidates[0] as default — this needs a stable, explainable order.

- Add endpointSortKey() with transparent observable signals: array items,
  detected fields, API path patterns, query params
- Update synthesize chooseEndpoint fallback to use itemCount + field count
- Sort key is internal only; not exposed as score to external consumers
2026-04-06 03:21:15 +08:00
tiaot33 5553300597 feat(linux-do): split topic content into a dedicated command (#821)
* feat(linux-do): split topic content into a dedicated command

Move the old main-post path out of linux-do topic so topic stays a summarized first-page reader while topic-content becomes the Markdown-focused entrypoint for full post bodies.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* feat(linux-do): update topic content handling to include YAML front matter

* fix(linux-do): update default output format to plain for topic-content rendering

* fix(linux-do): replace js-yaml with inline YAML serialization for topic-content

Adapters must only import node builtins, relative modules, or opencli
public APIs. Hand-roll the simple front matter serialization to remove
the third-party js-yaml dependency.

* fix(linux-do): refine YAML quoting to only escape colons followed by space

Colons in URLs (e.g. https://) are valid unquoted YAML values. Only
quote when a colon is followed by a space or appears at end of line.

---------

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-04-06 02:59:56 +08:00
jakevin d61dd7be0e refactor: extract shared scoring + consolidate time utils (#823)
* refactor: extract shared scoring logic and consolidate time format utils

- Extract applyUrlScoreAdjustments() and scoreArrayResponse() to analysis.ts,
  eliminating duplicated endpoint scoring between explore.ts and record.ts
- Consolidate formatDuration/formatUptime into a single formatDuration(ms)
  in download/progress.ts, reused by commands/daemon.ts

* fix: preserve explore scoring semantics and round daemon uptime

- Revert explore.ts scoreEndpoint to original inline /api/ /x/ bonus
  without record's tracking/analytics penalty (blocker from review)
- Math.round uptime*1000 to avoid floating-point noise in daemon status
2026-04-06 02:50:37 +08:00
jakevin e9867dcab0 feat(extension): v1.6.8 — fix scripting permission + refresh icons (#822)
* feat(extension): v1.6.8 — remove unused scripting permission, refresh icons

- Remove unused `scripting` permission (Chrome Web Store rejection fix)
- Bump version 1.6.7 → 1.6.8
- Redesign icons with neon gradient style (pure SVG paths, glow effect)

* revert icons to original, fix package.json version to 1.6.8

* test: remove stale scripting permission assertion
2026-04-06 02:07:00 +08:00
williamxie1989 bb7b26bc4a feat(xueqiu): add kline and groups adapters (#809)
* feat(xueqiu): add kline and groups adapters

Add kline.yaml: fetch candlestick/OHLCV data from Xueqiu v5 chart API.
Supports custom days lookback and outputs date, open, high, low, close,
volume, percent.

Add groups.yaml: list Xueqiu portfolio/group entries.


* fix(xueqiu): correct groups.yaml to use /portfolio/list.json API

The previous implementation used /portfolio/stock/list.json which only
returns stocks in a single group and does not return the group list.
Switch to /portfolio/list.json which returns all portfolio groups
including 实盘, 沪深, 港股, 美股, 模拟(pid=-4), 持仓 etc.


* fix(xueqiu): replace watchlist category param with pid selector

- Remove the unused 'category' parameter (the API ignores it;
  all groups live under category=1 regardless)
- Replace with 'pid' parameter to allow fetching any group:
  -4=simulated, -5=SH/SZ, -6=US stocks, -7=HK stocks, etc.
- API path still uses category=1 but pid is now user-controllable


---------
2026-04-06 02:01:29 +08:00
BruceLoveDecimal d2ae28786c feat:add 1688 assets downloadable (#820)
* feat:add 1688 assets downloadable

* fix: remove duplicate visitedRoots declaration and fix normalizeMediaUrl re-export

- Remove unused outer `visitedRoots` variable in scriptToReadAssets()
- Move normalizeMediaUrl test to import from shared.ts where it's defined
- Remove unused normalizeMediaUrl import from assets.ts

---------

Co-authored-by: 刘启灏 <liuqihao@liuqihaodeMacBook-Pro.local>
Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-04-06 01:59:39 +08:00
jakevin 1abff0cc1d feat(operate): unify network capture + implement CDP consoleMessages (#816)
* feat(operate): unify network capture + implement CDP consoleMessages

- operate open: start session capture before navigation (catches initial requests)
- operate network: prefer readNetworkCapture() over JS interceptor
- CDPPage: implement consoleMessages() via Runtime.consoleAPICalled

Part of #810

* fix(operate): use correct daemon/CDP entry field names for network capture

Daemon and CDP capture entries use responseStatus/responseContentType/
responsePreview (not status/contentType/responseBody). Fix the
normalization in operate network to match the actual entry shape from
extension/src/cdp.ts.

* fix(cdp): capture Runtime.exceptionThrown in consoleMessages

- Register Runtime.exceptionThrown handler to capture uncaught exceptions
  as error-level messages (most valuable diagnostic signal)
- 'error' filter now returns both console.error() and warning/exception
  entries, matching typical severity-based logging semantics
2026-04-05 22:55:03 +08:00
jakevin 1d46c5f934 feat(cdp): implement session-level network capture for CDPPage (#815)
* feat(cdp): implement session-level network capture for CDPPage

Implements startNetworkCapture() and readNetworkCapture() on CDPPage using
CDP Network domain events. Updates explore.ts to prefer session capture
over Performance API networkRequests().

Closes part of #810

* fix(cdp): use Network.loadingFinished for reliable body capture

- Move getResponseBody call from responseReceived to loadingFinished,
  matching the extension's implementation pattern
- Use extension-compatible entry shape (responseStatus, responseContentType,
  responsePreview) instead of custom field names
- Remove unreliable 100ms sleep hack in readNetworkCapture()
- Align with extension/src/cdp.ts:419-437 for consistency

* fix(cdp): drain buffer on readNetworkCapture to match daemon contract

readNetworkCapture() must clear the buffer after reading, matching the
daemon Page's read-and-drain behavior. Without this, repeated reads
would return stale entries.

* fix(cdp): await in-flight body fetches before returning from readNetworkCapture

Track all pending getResponseBody promises and await them in
readNetworkCapture() before draining the buffer. This ensures
explore/diagnostic consumers always get entries with responsePreview
populated, not empty shells where the body fetch hasn't resolved yet.

* fix(explore): handle both legacy and capture entry field names

parseNetworkRequests now maps both shapes:
- Legacy: status, contentType, responseBody
- Capture (extension/CDP): responseStatus, responseContentType, responsePreview

Also clears _pendingBodyFetches on startNetworkCapture reset.
2026-04-05 22:50:55 +08:00
jakevin d7fe7a7ffa fix(scaffold): replace non-existent extract step with select in YAML template (#814) 2026-04-05 22:50:43 +08:00
jakevin 7b55b8c595 test: remove flaky bloomberg e2e tests (#818)
* test: remove flaky bloomberg e2e tests

Bloomberg RSS endpoints are unreliable in CI, causing intermittent
e2e-headed failures unrelated to code changes.

* test: remove flaky bloomberg e2e tests

Bloomberg RSS feeds are unreliable in CI, causing false failures
in e2e-headed runs. Remove bloomberg tests from both
public-commands.test.ts and browser-public-extended.test.ts.
2026-04-05 22:50:24 +08:00
jakevin 15268da8f3 fix: add safety boundaries to diagnostic output (#806)
* fix: add safety boundaries to diagnostic output

- Redact sensitive headers (Authorization, Cookie, etc.) from network requests
- Redact sensitive URL query parameters (token, key, secret, etc.)
- Cap individual fields: snapshot (100K chars), adapter source (50K chars),
  network requests (50 entries, 4K body each), stack trace (5K chars)
- Enforce 256KB total output budget with graceful degradation:
  drops snapshot first, then page state entirely
- Export truncate/redactUrl helpers for testing

* fix: add free-text redaction for all diagnostic string channels

Addresses review feedback: snapshot, consoleErrors, error message/hint/stack
could contain inline secrets (Bearer tokens, JWTs, cookie values, token=value
patterns). All string channels now pass through redactText() before emission.

- Add redactText() with patterns for Bearer tokens, JWTs, cookie values,
  and inline key=value secrets
- Apply redactText to: error.message, error.hint, error.stack,
  page.snapshot, page.consoleErrors
- Add 6 new test cases for redactText and error message redaction

* fix: resolve adapter source path and add page state collection timeout

Fixes #808 items 1 and 3:

1. adapter.source was missing for all command types because buildRepairContext
   only checked cmd._modulePath (set only for manifest lazy-loaded TS).
   Now resolveAdapterSourcePath() checks cmd.source first, skips manifest:
   pseudo-paths, and maps dist/clis/*.js back to source clis/*.ts.

3. collectPageState() had no timeout — a hung CDP connection would block
   error propagation indefinitely. Now wrapped with 5s Promise.race timeout,
   falling back to emitting diagnostic without page state.

* fix: track sourceFile in manifest for YAML adapter source resolution

YAML commands inlined in the manifest previously lost their original file
path, causing resolveAdapterSourcePath() to return undefined. Add
sourceFile field to ManifestEntry so discovery can reconstruct the
editable source path for both YAML and TS commands.
2026-04-05 19:50:03 +08:00
jakevin a3efdc16de refactor: centralize build path resolution (#807) 2026-04-05 19:46:58 +08:00
jakevin d51338cbf3 chore: bump version to 1.6.7 v1.6.7 2026-04-05 18:07:55 +08:00
jakevin 664a971ed5 feat: structured diagnostic output for AI-driven adapter repair (#802)
* feat: add structured diagnostic output for AI-driven adapter repair

When OPENCLI_DIAGNOSTIC=1 is set, failed commands emit a RepairContext
JSON to stderr containing the error, adapter source, and browser state
(DOM snapshot, network requests, console errors). AI Agents consume
this to diagnose and fix adapters when websites change.

Also adds the opencli-repair skill guide for AI Agents.

* fix: correct e2e test binary path to dist/src/main.js

The e2e helpers pointed to dist/main.js but the actual build output
is at dist/src/main.js (matching package.json "main" field). This
caused all e2e-headed tests to fail with "Cannot find module".

* fix: correct dist/main.js path in autoresearch scripts

* fix: emit diagnostic for pre-session browser failures

When browser connection fails before the session callback runs
(e.g., BrowserConnectError), the inner diagnostic catch never fires.
Use a flag to ensure the outer catch emits diagnostic as a fallback.

* test: tolerate unavailable Bloomberg RSS feeds in e2e

* test: skip flaky bloomberg businessweek e2e test

The Bloomberg Businessweek RSS feed is intermittently unavailable,
causing CI failures unrelated to code changes.

* revert: restore bloomberg businessweek e2e coverage
2026-04-05 18:04:49 +08:00
Kai 97a547c6c5 fix: avoid inserting completion config inside multi-line shell commands (#796)
* fix: avoid inserting completion config inside multi-line shell commands

The postinstall zshrc insertion logic splits backslash-continued blocks
(e.g. zinit stanzas) when it finds a compinit match inside them, which
breaks the user's shell config. Walk backward past continuation lines
so the insertion lands before the entire logical command.

* fix: append zsh completion to end of .zshrc instead of splicing

Replace the fragile compinit-searching splice logic with a simple
append, matching the strategy already used for bash. This avoids
breaking multi-line commands (e.g. zinit blocks with zicompinit).

Still detects existing compinit to avoid adding a duplicate call.

* fix: stop modifying shell rc files in postinstall

Replace the fragile .zshrc/.bashrc modification logic with a safer
approach: only write completion files and print setup instructions.

The previous approach tried to parse and splice into rc files, which
broke multi-line shell commands (e.g. zinit blocks with backslash
continuations matching /compinit/). Instead of attempting to fix the
parser, remove rc modification entirely — this matches the approach
used by rustup, homebrew, and other CLI tools.

Closes #788

---------

Co-authored-by: jackwener <jakevingoo@gmail.com>
2026-04-05 17:39:23 +08:00
jakevin eedc47aa26 chore: bump version to 1.6.6 v1.6.6 2026-04-05 17:34:57 +08:00
jakevin 8c41411860 fix: route copied adapters through opencli exports
* fix(discovery): expose runtime deps to user adapters

* fix: route copied adapters through opencli exports

* refactor: route adapter status output through logger
2026-04-05 17:31:45 +08:00
jakevin ed69e839ab chore: bump version to 1.6.5 (#797) v1.6.5 2026-04-05 16:07:02 +08:00
jakevin 4fe9a73ebc refactor: migrate adapter imports to package exports (#795)
* refactor: migrate adapter imports to package exports

Replace all relative imports (../../src/registry.js, ../../browser/cdp.js, etc.)
with package exports (@jackwener/opencli/registry, @jackwener/opencli/errors, etc.)
across all 484 adapter files.

This decouples adapter import resolution from directory structure:
- User CLIs in ~/.opencli/clis/ resolve via node_modules symlink
- Internal adapters resolve via Node.js self-referencing
- No more shim files needed for import resolution

Changes:
- package.json: add sub-path exports for all public modules
- clis/**: replace relative imports with @jackwener/opencli/...
- discovery.ts: simplify ensureUserCliCompatShims to symlink-only
- registry-api.ts: export CommandArgs type
- Remove root-level shim directories (browser/, download/, pipeline/)
- Remove shim entries from tsconfig.json include and package.json files

* test: add regression tests for package exports

Prevents regressions like #788/#791 by:
1. Scanning all adapter files for forbidden relative imports
   (../../src/, ../../browser/, etc.) — fails if any remain
2. Verifying every package.json export maps to an existing source file

18 new test cases.

* fix: use junction on Windows + broaden test patterns

- discovery.ts: use 'junction' symlink type on Windows (no admin required)
- package-exports.test.ts: generalize forbidden patterns to catch any
  depth of ../ traversal (not just ../../ and ../../../)

* fix: update stale vi.mock/importActual paths in adapter tests

Test files still used old relative paths for vi.mock() and
vi.importActual() calls. Updated 5 test files to use package exports.
Also broadened regression test patterns to catch mock/importActual paths.

* fix: use rm instead of unlink for symlink cleanup, add warn on failure

Addresses review feedback from Astro-Han:
- rm() handles both symlinks and stale directories (unlink fails on dirs)
- Log a warning when symlink creation fails instead of silent catch

* docs: update import examples to use package exports

Update all documentation, contributing guides, and skills to use
@jackwener/opencli/registry instead of ../../src/registry.js.

Without this, users following the docs would write adapters with
broken imports since the old shim files are no longer created.
2026-04-05 16:02:17 +08:00
jakevin a1dd817886 chore: bump version to 1.6.4 (#794) v1.6.4 2026-04-05 14:57:45 +08:00
AstroHan 20957cbc7b fix: resolve version 0.0.0 and user CLI load failures (#788) (#789)
Bug 1: version.ts used a single-level parent lookup for package.json,
which broke after #784 changed rootDir from "src" to "." (version.js
now lives in dist/src/ instead of dist/).  Walk up until package.json
is found — works in both dev (src/) and prod (dist/src/).

Bug 2: adapters copied to ~/.opencli/clis/ import ../../src/registry.js
etc., which resolves to ~/.opencli/src/.  Derive src/ compat shims from
the existing rootShims list so these imports resolve correctly.
2026-04-05 14:54:30 +08:00