Repository navigation
feat(extensions): ship web access as a ThinkRail extension whose switch also covers its skills - #965
Merged
Merged
Conversation
…ch also drops its skills
…s and reload again after a mid-reload toggle
Rinat S (rsolmano)
requested review from
Olga Lavrichenko (OLavrik),
Rustam Sadykov (SBOne-Kenobi) and
danyaberezun
as code owners
October 27, 2026 23:18
🌐 Website previewPreview retired when this pull request closed. |
danyaberezun
left a comment
Collaborator
There was a problem hiding this comment.
One regression worth fixing before merge, plus two notes on races (the second pre-existing and non-blocking) — all inline.
…hile the web-access extension is off
5 tasks done
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.
Problem
Web access (
web_search,fetch_content,get_search_content) comes from the third-party pi packagepi-web-access, and it was the last pi capability ThinkRail wired in through special cases instead of as a ThinkRail extension:BundledExtensions.webAccessFactory,BuildRuntimeSources.webAccessIndex, a generatedbundledWebAccessFactory).librarianskill (research open-source libraries with GitHub permalinks), which ThinkRail never loaded, even thoughpi installwould.Approach
thinkrail-extensions/web-access(server half only) wraps the package unchanged for chats and subagents. The host keeps its headless-search policy (defaultweb_searchworkflowto"none"), composed unconditionally: it compensates for the host's UI and must also cover a user's ownpi-web-access, which runs exactly when the extension is off. It loads everything the package declares, tools andlibrarian, the waypi installwould. There's nothing of ours to publish, so the usual three-PR template collapses to this one (documented inthinkrail-extensions/SPEC.md). The chat cards stay app-local and join by tool name untilMarkdown/Collapsible/ToolFileLinkare in the UI SDK..tsvs stricttsc:server/piWebAccess.js+.d.ts, sotscstops at the declaration. The.jsloads the package lazily:mainpasses the same probe.thinkrail-extensions/SPEC.md), like removing a package in pi:additionalSkillPaths, rebuilt in place on each reload. pi resolves same-name skills first-wins, so dropping a winner afterwards would also lose a user's own~/.claude/skills/librarian.skills/host/and extension skills underskills/extensions/<name>/, so ownership survives flattening.Changes
@thinkrail/ext-web-access(./server), registered inpackages/server/src/extensions/registry.ts.pi-web-accessandjitimove frompackages/serverto it.BundledExtensions.webAccessFactory,BuildRuntimeSources.webAccessIndex,bundledWebAccessFactory, the dev jiti loader, and the devpi-web-accessextension path. The headless policy moved toagent/headlessSearch.ts, unchanged in behavior.BuildRuntimeSources.skillRootsis now{ source, route }[]. New exports fromextensions:STAGED_HOST_SKILLS_ROUTE,stagedExtensionSkillRoute,extensionSkillRoots. Staged skills layout changed (skills/host/…,skills/extensions/web-access/librarian/…); the CLI smoke and artifact probes are updated.agent/extensions.tsbuilds skill inputs from the disabled-extensions snapshot;agentSessionManager.applyExtensionToolsadds the skill reload and the mid-reload follow-up.settings.extensions.web-access.descriptionin en/es/ja/zh-CN), and the Settings blurb now says tools and skills.thinkrail-extensions, newmodule-ext-web-access, serverextensions/agent, cli, desktop, web tools, spec-graph.pi-web-accessfrom 0.13.0, and listing an extension's skills in its Settings row.Closest look: the reload rule in
applyExtensionToolsandresolveSkillInputs/bundledSkillPathsinagent/extensions.ts.Screenshots
Settings → Extensions, fixture project, same viewport:
Related issues
Part of #600 (the
web-accessstep: the first extension wrapping a third-party pi package).Checklist
bun run lint,bun run typecheck,bun run testbun run e2e; agent behavior covered by the focused live specbun run e2e:full e2e/web-tools.live.spec.ts, not the completee2e:full)SPEC.md/ top-level specs updated to reflect any boundary, contract, or behavior changeTesting
On the rebased head unless noted:
bun run lint,bun run typecheck(25/25),bun run test(25/25),check:compiler,check:deps,check:boundaries,check:seams,check:spec-surface,check:i18n→ greenbun run e2e→ 7/8 shards passed; the 1 failure (changes.spec.ts"A failed read says so", unrelated) passes on rerun:bun run e2e e2e/changes.spec.ts→ 31/31bun run e2e:full e2e/web-tools.live.spec.ts→ 2 passed (realfetch_content/web_searchcards) — run before the rebase; covers unchanged inputsbun run build:binary+bun run smoke:binary→ OK, including the stagedlibrarianprobebun run e2e:binary→ 621 passed, 11 failed in terminal/workspace/layout/model-picker specs. Those 4 specs rerun → 46/46 passed (load flakes, unrelated; before the rebase)@thinkrail/server/agentand building a loader → passes (fails with a static import)web_searchworks; the agent sees all 3 tools andlibrarian;/skill:librarianand Settings → Skills are present.fetch_content https://example.com→ "Example Domain".Review round 1 (danyaberezun)
f20728597: the headless policy is host-owned and unconditional again. Regression: a user's ownpi-web-accesswith the extension off →workflow: "none".e8c26c943: a follow-up reload happens only when the extension policy generation moved during the reload. Regression: an unchanged or skill-less refresh during a reload → no second reload. Both race tests pass 10/10.pi-web-accessstate: pre-existing, filed as pi-web-access shares fetch/result/clone state across chats, so one chat's reload aborts another's web work #976.bun run e2e→ all 8 shards passed;bun run e2e:full e2e/web-tools.live.spec.ts→ 2 passed;bun run test→ green except the terminal test "closing a tab removes it and reports closed", which fails intermittently on the base too (2/6 runs).