Skip to content

fix(ts-client): bypass browser cache for workspace file downloads - #6182

Open
BORAN002 wants to merge 4 commits into
OpenHands:mainfrom
BORAN002:fix/file-download-browser-cache
Open

BORAN002 wants to merge 4 commits into
OpenHands:mainfrom
BORAN002:fix/file-download-browser-cache

Conversation

@BORAN002

@BORAN002 BORAN002 commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

HUMAN:

I want file downloads to reflect the current workspace contents, especially after an agent updates a file. Returning cached bytes makes file previews misleading.


AGENT:

Why

Workspace file paths are mutable, but the TypeScript client uses the default fetch cache policy for downloads. Chromium can reuse an old response after the file changes, so downloading the same path again returns stale content. This is the SDK dependency identified in Canvas PR #18603.

Summary

  • Forward the standard RequestCache option through HttpClient.
  • Use cache: 'no-store' in FileClient.downloadFile() and RemoteWorkspace.fileDownload().
  • Add regression coverage for host, conversation-scoped and legacy cid requests, including unchanged cache defaults on other operations. A separate lockfile-only commit refreshes transitive Zod to 4.6.7 to clear the pre-existing production dependency audit failure.

Issue Number

Fixes #6181.

How to Test

From clients/typescript/ after npm ci:

npm test -- src/__tests__/api-clients.test.ts src/__tests__/conversation-scope.test.ts src/__tests__/remote-workspace-download.test.ts
npm run test:coverage
npm run lint
npm run build
npm run format:check
npm run test:public-type-budget
npm run check:public-type-budget
npm run test:agent-server-api-tooling
npm run check:agent-server-api
npm audit --audit-level=moderate --omit=dev
npm audit --audit-level=high --production

Results: the new download assertions failed on base (8 failed / 105 passed); the focused suite passed after the fix (113 passed). The full client suite passed 400 tests across 27 files. Build, formatting, public type-budget, API-contract and per-file pre-commit checks passed. Lint reported 0 errors and 5 existing warnings on unchanged lines.

Real browser validation used Google Chrome 155 on macOS arm64, the built TypeScript client and an unmodified source Agent Server (both 1.58.1), with browser caching enabled:

Scenario Base Fixed
Host FileClient PNG download Old bytes Current bytes
Host RemoteWorkspace text download Old text Current text
Conversation-scoped FileClient PNG download Old bytes Current bytes
Conversation-scoped RemoteWorkspace text download Old text Current text

Base: acd96e6fa424c02432304395b9208f99be24b54d. Cache implementation: be042f557997575f6ba046666adbe043fef45e72. Revalidated after the dependency refresh at 0eef7e6352dd39179035384eaa5e953138bd171a; head 8bb2118a only updates evidence. A clean installation, all 400 tests, and all four browser scenarios passed again.

The browser downloads an owned fixture, the fixture is overwritten, and the same URL is downloaded again. Initial mtime is set to 2020-01-01 to make Chromium's heuristic freshness reproducible. Direct HTTP reads check the current bytes independently. Chrome recorded 8 cached responses on base and 0 with the fix, including second reads and invalid-key controls. Invalid-key network requests returned 401 throughout; the fixed browser also returns 401 instead of reusing previously downloaded data.

Reproduction instructions, script and JSON evidence. The script adapts the earlier public probe linked in Canvas PR #18603 and uses no response mocks or request interception.

Video/Screenshots

These captures show the diagnostic runner in real Chrome, not the Agent Canvas Files UI.

Before · After

Design Doc

Small transport fix; rationale and verification are in the linked evidence README.

Type

  • Bug fix
  • Feature
  • Refactor
  • Breaking change
  • Docs / chore

Notes

  • Issue [Bug]: TypeScript file downloads can return stale browser-cached bytes after a file update #6181 has completed triage and is labeled ready-for-dev.
  • Browser caching changes only for workspace file downloads. Server headers, response decoding and trajectory downloads are unchanged.
  • The separate RemoteWorkspace binary-decoding fix in fix(ts-client): keep binary bytes in RemoteWorkspace downloads #5762 is outside this change; PNG fidelity is checked through FileClient and RemoteWorkspace uses text fixtures.
  • The initial security audit failed on GHSA-mrhx-c7xc-m3w5, also reproduced with the unchanged base lockfile. Commit 0eef7e63 updates only Zod's locked version, tarball URL and integrity from 4.3.6 to 4.6.7. It satisfies OpenRouter's existing version range; the manifest, project version and all other locked packages are unchanged. Both production audit commands now pass with zero findings. Downstream apps retaining their own older lockfiles still need to update their resolution.
  • The current-head TypeScript CI passes all jobs, including security, tests, build, public type budget and API contract. Broader CI status is shown in the Checks tab.
  • No local LLM calls or agent benchmarks were run. The local browser evidence covers the SDK and source Agent Server, not the Canvas Files UI or a published npm release.

BORAN002 and others added 2 commits October 24, 2026 12:41
Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: openhands <openhands@all-hands.dev>
@github-actions

Copy link
Copy Markdown
Contributor

📁 PR Artifacts Notice

This PR contains a .pr/ directory with temporary PR-specific documents. The directory will be automatically removed after this PR merges to main through a cleanup PR.

BORAN002 and others added 2 commits October 24, 2026 14:04
Update only the transitive Zod resolution from 4.3.6 to 4.6.7 for GHSA-mrhx-c7xc-m3w5. The package manifest and all other locked packages are unchanged.

Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: openhands <openhands@all-hands.dev>
@BORAN002
BORAN002 marked this pull request as ready for review October 24, 2026 06:11

@all-hands-bot all-hands-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This review was posted by an AI agent (OpenHands).

Reviewed head 8bb2118acf874eeac0bd51285befb1e2378c36c1 against main. No material correctness, security, compatibility, or acceptance-criterion findings.

Scope. clients/typescript/ owns the browser-compatible TypeScript client in this repository, and the fix stays inside that boundary. Linked issue #6181 is open with priority:medium and ready-for-dev.

Change review. HttpClient gains an optional cache?: RequestCache that is only forwarded to RequestInit when set, so every existing operation keeps its previous default behavior byte-for-byte; the Node fallback path (requestWithBodyOnGet) is not reachable for GET-without-body downloads. FileClient.downloadFile() (with downloadTextFile() delegating to it) and RemoteWorkspace.fileDownload() (with downloadAsText/downloadAsBlob/downloadAndSave delegating to it) use cache: 'no-store', covering all workspace file download paths. Trajectory and cloud export downloads are intentionally unchanged, consistent with the stated non-goals. Regression tests cover host, conversation-scoped (scoped-support true/false including the legacy cid fallback), and assert other operations keep an undefined cache.

Dependency bump. The lockfile-only zod 4.3.6 → 4.6.7 update is the only manifest-adjacent change. Zod 4.6.7 was published to npm on 2026-10-12 (15 days before this review), clearing the repository's seven-day package-index supply-chain guardrail. Both production audit commands report zero findings on the current lockfile.

Verification on this head. All GitHub Actions checks pass on 8bb2118a (tests, security, build, public type budget, API contract). Locally reproduced from a clean npm ci: focused suites pass 113 tests, full client suite passes 400 tests across 27 files, lint reports 0 errors, build/coverage/public-type-budget/agent-server API contract and tooling checks pass, and both production audits are clean.

Live evidence. The failure mode is browser-cache-specific and cannot be forged by unit tests, and the PR provides authentic before/after evidence: real Chrome against an unmodified source Agent Server, stale bytes and 8 cached responses on base acd96e6f, current bytes and 0 cached responses on the fix, with mtime-set fixtures for reproducible heuristic freshness, direct HTTP reads as an independent check, and 401 invalid-key controls confirming no stale reuse. This meets the repository's live-evidence checkpoint for a production-runtime bug fix, with the environment differences (Chrome 155/macOS, not the Canvas UI or a published npm release) explicitly disclosed.

✅ APPROVED

@all-hands-bot
all-hands-bot requested a review from enyst October 29, 2026 06:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: TypeScript file downloads can return stale browser-cached bytes after a file update

2 participants