[fix]: add support for local caching of agent when using api (2)#1521
[fix]: add support for local caching of agent when using api (2)#1521seanmcguire12 merged 9 commits intomainfrom
Conversation
🦋 Changeset detectedLatest commit: cda468f The changes in this PR will be included in the next version bump. This PR includes changesets to release 3 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
✱ Stainless preview buildsThis PR will update the ⚡ stagehand-python studio · conflict
|
| id: $response.body#/data/sessionId | ||
| description: End the session and release resources | ||
| schemas: | ||
| AgentCacheContext: |
There was a problem hiding this comment.
This should just be a boolean - something like useCaching. AgentCacheContext and AgentCacheContextOutput makes us stray even further from the REST/resource model. The main issue is that it leaks internals & makes future changes harder because clients now depend on cache mechanics.
Long-term we want an interface that’s basically just GET/POST resources — like GET /products/{productId} returns a product, not “a product + instructions for how the warehouse finds it”.
Rule of thumb: clients should describe what they want, not how we optimize it internally.
646ca3d to
89f3a74
Compare
Greptile SummaryThis PR implements local agent caching when executing through the API. When a Key Changes:
Architecture: Previous Review Comments: Confidence Score: 4/5
Important Files Changed
Sequence DiagramsequenceDiagram
participant Client as V3 Client
participant API as StagehandAPIClient
participant Server as API Server
participant Handle as ServerAgentCacheHandle
participant MemCache as In-Memory AgentCache
participant LocalCache as Local CacheStorage
Note over Client,LocalCache: Agent Execute with API Mode + Caching
Client->>Client: Check if cacheContext exists
alt Has cacheContext
Client->>LocalCache: Try to read cache entry
LocalCache-->>Client: Return cached result or null
end
alt Cache miss or no cache
Client->>API: agentExecute(config, options, shouldCache=true)
API->>Server: POST /sessions/{id}/agentExecute
Server->>Handle: createInMemoryAgentCacheHandle()
Handle->>MemCache: Create memory-backed AgentCache
Handle->>Server: Replace V3.agentCache with MemCache
Server->>Server: Execute agent task
Server->>MemCache: Record agent steps (in memory)
MemCache->>MemCache: Store to Map (bufferLatestEntry=true)
Server->>Handle: handle.complete()
Handle->>MemCache: consumeBufferedEntry()
MemCache-->>Handle: Return AgentCacheTransferPayload
Handle->>Server: Restore original cache
Handle-->>Server: Return payload
Server->>API: SSE: finished event with cacheEntry
API->>API: Store finishedData.cacheEntry
API-->>Client: Return AgentResult
Client->>API: consumeLatestAgentCacheEntry()
API-->>Client: Return AgentCacheTransferPayload
Client->>LocalCache: storeTransferredEntry(payload)
LocalCache->>LocalCache: Write to local cache file
end
Note over Client,LocalCache: Subsequent executions use local cache
|
| const finishedData = | ||
| this.consumeFinishedEventData<Api.AgentExecuteResult>() ?? null; | ||
| this.latestAgentCacheEntry = | ||
| finishedData?.cacheEntry !== undefined | ||
| ? (finishedData.cacheEntry as AgentCacheTransferPayload) | ||
| : null; |
There was a problem hiding this comment.
style: The null coalescing on line 379 (?? null) is redundant since entry is already null if latestAgentCacheEntry is null
| const finishedData = | |
| this.consumeFinishedEventData<Api.AgentExecuteResult>() ?? null; | |
| this.latestAgentCacheEntry = | |
| finishedData?.cacheEntry !== undefined | |
| ? (finishedData.cacheEntry as AgentCacheTransferPayload) | |
| : null; | |
| const finishedData = | |
| this.consumeFinishedEventData<Api.AgentExecuteResult>() ?? null; | |
| this.latestAgentCacheEntry = | |
| finishedData?.cacheEntry !== undefined | |
| ? (finishedData.cacheEntry as AgentCacheTransferPayload) | |
| : null; |
Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/core/lib/v3/api.ts
Line: 374:379
Comment:
**style:** The null coalescing on line 379 (`?? null`) is redundant since `entry` is already `null` if `latestAgentCacheEntry` is `null`
```suggestion
const finishedData =
this.consumeFinishedEventData<Api.AgentExecuteResult>() ?? null;
this.latestAgentCacheEntry =
finishedData?.cacheEntry !== undefined
? (finishedData.cacheEntry as AgentCacheTransferPayload)
: null;
```
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
2 issues found across 12 files
Prompt for AI agents (all issues)
Check if these issues are valid — if so, understand the root cause of each and fix them.
<file name="packages/server/openapi.v3.yaml">
<violation number="1" location="packages/server/openapi.v3.yaml:87">
P3: The `entry` property is missing the `type` field. Other flexible-type fields in this spec use `type: unknown` (e.g., `ExtractResult.result`, `NavigateResult.result`). For consistency with codebase conventions, consider adding `type: unknown` here.</violation>
</file>
<file name="packages/core/lib/v3/cache/CacheStorage.ts">
<violation number="1" location="packages/core/lib/v3/cache/CacheStorage.ts:84">
P2: Memory store holds direct references, unlike file storage which deep-copies via JSON serialization. Mutations to the original data or read results will unexpectedly modify cached values. Consider cloning data to match file storage semantics:
```typescript
this.memoryStore.set(fileName, JSON.parse(JSON.stringify(data)));
```</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated. # Releases ## @browserbasehq/stagehand@3.0.8 ### Patch Changes - [#1514](#1514) [`40ce5cc`](40ce5cc) Thanks [@tkattkat](https://github.com/tkattkat)! - Rename the close tool in agent to "done" - [#1574](#1574) [`5506f41`](5506f41) Thanks [@tkattkat](https://github.com/tkattkat)! - fix(server): pass cdpUrl to localBrowserLaunchOptions when launchOptions absent - [#1521](#1521) [`84c05ca`](84c05ca) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - fix: get agent cache working in API mode - [#1486](#1486) [`692ffa0`](692ffa0) Thanks [@tkattkat](https://github.com/tkattkat)! - improve logging in agent - [#1551](#1551) [`1ef8901`](1ef8901) Thanks [@miguelg719](https://github.com/miguelg719)! - move extract handler response log to after URL injection - [#1495](#1495) [`72ac775`](72ac775) Thanks [@tkattkat](https://github.com/tkattkat)! - export tool function & type to simplify defining custom tools - [#1481](#1481) [`3d5af07`](3d5af07) Thanks [@tkattkat](https://github.com/tkattkat)! - add waitForTimeout to page - [#1423](#1423) [`40e1d80`](40e1d80) Thanks [@miguelg719](https://github.com/miguelg719)! - Improve benchmark handling and add metadata - [#1588](#1588) [`56c0d24`](56c0d24) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - add SnapshotOptions to page.snapshot() - [#1483](#1483) [`16d72fb`](16d72fb) Thanks [@tkattkat](https://github.com/tkattkat)! - Optimize screenshot handling in agent hybrid mode - [#1498](#1498) [`088c4cc`](088c4cc) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - fix: replaying cached actions (for agent & act) now uses the originally defined model, (instead of default model) when action fails and rerunning inference is needed - [#1575](#1575) [`4276f4a`](4276f4a) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - expose port param in localBrowserLaunchOptions - [#1544](#1544) [`6005786`](6005786) Thanks [@tkattkat](https://github.com/tkattkat)! - Recommend hybrid mode over DOM mode in agent, which is now considered legacy - [#1505](#1505) [`6fbf5fc`](6fbf5fc) Thanks [@tkattkat](https://github.com/tkattkat)! - Add structured output to agent result + ensure close tool is always called - [#1511](#1511) [`704cf18`](704cf18) Thanks [@shrey150](https://github.com/shrey150)! - Fix ControlOrMeta keypress event - [#1480](#1480) [`091296e`](091296e) Thanks [@tkattkat](https://github.com/tkattkat)! - Update agent to only calculate xpath when caching is enabled - [#1509](#1509) [`e56c6eb`](e56c6eb) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - add support for page.waitForSelector() - [#1478](#1478) [`2cb78d0`](2cb78d0) Thanks [@tkattkat](https://github.com/tkattkat)! - update agent message handling - [#1518](#1518) [`5dad639`](5dad639) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - add page.snapshot() for capturing a stringified DOM snapshot of the page, including an xpath map & url map - [#1576](#1576) [`b7c2571`](b7c2571) Thanks [@tkattkat](https://github.com/tkattkat)! - utilize waitForSelector when running agent cache - [#1560](#1560) [`4c69117`](4c69117) Thanks [@tkattkat](https://github.com/tkattkat)! - Update coordinate handling in cua and hybrid ## @browserbasehq/stagehand-server@3.5.0 ### Minor Changes - [#1578](#1578) [`a5074bd`](a5074bd) Thanks [@monadoid](https://github.com/monadoid)! - /end endpoint no longer takes an empty object - instead, no request body is required. ### Patch Changes - Updated dependencies \[[`40ce5cc`](40ce5cc), [`5506f41`](5506f41), [`84c05ca`](84c05ca), [`692ffa0`](692ffa0), [`1ef8901`](1ef8901), [`72ac775`](72ac775), [`3d5af07`](3d5af07), [`40e1d80`](40e1d80), [`56c0d24`](56c0d24), [`16d72fb`](16d72fb), [`088c4cc`](088c4cc), [`4276f4a`](4276f4a), [`6005786`](6005786), [`6fbf5fc`](6fbf5fc), [`704cf18`](704cf18), [`091296e`](091296e), [`e56c6eb`](e56c6eb), [`2cb78d0`](2cb78d0), [`5dad639`](5dad639), [`b7c2571`](b7c2571), [`4c69117`](4c69117)]: - @browserbasehq/stagehand@3.0.8 ## @browserbasehq/stagehand-evals@1.1.7 ### Patch Changes - Updated dependencies \[[`40ce5cc`](40ce5cc), [`5506f41`](5506f41), [`84c05ca`](84c05ca), [`692ffa0`](692ffa0), [`1ef8901`](1ef8901), [`72ac775`](72ac775), [`3d5af07`](3d5af07), [`40e1d80`](40e1d80), [`56c0d24`](56c0d24), [`16d72fb`](16d72fb), [`088c4cc`](088c4cc), [`4276f4a`](4276f4a), [`6005786`](6005786), [`6fbf5fc`](6fbf5fc), [`704cf18`](704cf18), [`091296e`](091296e), [`e56c6eb`](e56c6eb), [`2cb78d0`](2cb78d0), [`5dad639`](5dad639), [`b7c2571`](b7c2571), [`4c69117`](4c69117)]: - @browserbasehq/stagehand@3.0.8 Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
why
what changed
test plan
Summary by cubic
Adds local agent caching when executing via the API. When a cacheContext is provided, agent cache entries returned by the server are saved to local cache for replay and faster repeats.
Written for commit cda468f. Summary will update on new commits.