feat(agent): add browser self-healing and durable overrides - #292
Open
IRONICBo wants to merge 2 commits into
Open
feat(agent): add browser self-healing and durable overrides#292IRONICBo wants to merge 2 commits into
IRONICBo wants to merge 2 commits into
Conversation
|
@IRONICBo is attempting to deploy a commit to the socai Team on Vercel. A member of the Team first needs to authorize it. |
This was referenced Sep 6, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
browser_scriptrecovery tool for browser-backed site-tool failures~/.socai/tool-overrides/<site>/<tool>/and transparently reuse it on later callsstale, re-certifiedactive, orquarantinedsocai.evaluate/socai.waitForProduction evidence
The original v0.5.5 XHS failure observed the requested query in the search input while the browser remained on
/explore. The run saw 32 homepage cards, returned zero search results, and reportedSearch did not transition to a valid Xiaohongshu result page. PR #291 fixes that concrete composer transition on main; this PR supplies a generic local recovery path for the next site DOM/protocol change without requiring a Rust toolchain on the user's machine.A logged-in XHS livestream task then exposed a bridge compatibility bug. The agent correctly called
socai.evaluate(() => ({ ... })), but JSON serialization omitted the function-valuedscriptmember and Rust returnedbrowser-script operation requires 'script'. After normalizing function arguments to source, four consecutive calls completed, entered/livelist, and returned the live categories/cards.Root cause
The existing high-level tools encode selectors, page transitions, and extraction contracts in Rust. When a site changes those assumptions, the running binary can provide good failure evidence but previously had no safe way to probe the live DOM, validate a replacement, retain it locally, and continue the original task.
The first bridge implementation also documented function arguments but only transported strings.
JSON.stringifydrops function-valued object properties, so an otherwise validsocai.evaluate(() => ...)request arrived withoutargs.script.The initial persistence design retained overrides indefinitely across upgrades. That could hide a repaired native implementation, reuse an incompatible local contract, or make rollback fail if an older binary encountered a newer manifest schema.
Implementation
LocalOverrideTool; successful built-ins are unchanged, while repairable browser failures return an explicitrecovery.action:"browser_script"type()to a unique marker on the exact visible selector match and refuse to type if click focus moved elsewhereok:true, matching query/author/note IDs, non-empty activation evidence, and usable per-item identity/content/handoff fields before activation; validate the same contract again on every reuseok:trueis not success_socai_local_overrideand an artifact path on reused results; when a failed upgrade canary may have produced partial page/artifact/history/enrichment effects, report that explicitlyPersistent overrides are intentionally limited to XHS
search,get_notes, andauthor_scan, plus Douyinsearch. Login, captcha, security verification, rate limits, permissions, true empty results, provider errors, media failures, and OCR failures are not repair triggers. Browser JavaScript has page authority only and receives no host shell or filesystem API.Persistence, upgrades, and rollback
The agent first probes without
save_as. Once the complete replacement returns contract-valid, non-empty evidence, it callsbrowser_scriptwithsave_as.tool. The runtime performs blocker preflight, writes the candidate, reads and executes the exact disk bytes, performs blocker postflight and contract validation, then atomically publishes the activation manifest. The next ordinary tool call verifies the latest manifest and script hash and reuses it automatically.The manifest records
source_version,validated_with_version,tool_contract_version,tool_impl_revision, timestamps, status, and reason. On a release or implementation revision change, the new built-in runs once. A contract-valid native success appendsstale; a repairable native failure allows the old script to run and be re-certified; a contract change appendsquarantined. Activation records stay schema v2 so an older binary can still read them, while newer lifecycle-only records use a separatestate-*v3 namespace that the old reader ignores.Ad-hoc live-page inspection without
save_asis recorded in the run but is not persisted as an override.Validation
cargo test -p socai-core --lib— 99 passed, 0 failed, 2 ignoredcargo test -p socai-cli— 6 passed, 0 failedcargo check --workspace --all-targetsnode --check core/src/sites/xhs/page_scripts.jsgit diff --checksocai.evaluatecalls completed and the task entered/livelistJSON.stringifyandTextEncoder, the isolated world still read the same DOM and returned the expected JSON and byte countNo new Rust test function was added, following the repository engineering rule; browser-only behavior was exercised against real Chrome and existing suites cover the shared Rust build.