[STG-1427] feat: per-method serverCache threshold configuration#2155
[STG-1427] feat: per-method serverCache threshold configuration#2155BABTUNA wants to merge 2 commits into
Conversation
Extends serverCache to accept boolean | { threshold: number } on
act/extract/observe options and on the Stagehand constructor, with
the constructor additionally accepting a per-method object
({ act, extract, observe }) for fine-grained control.
Method-level options take precedence over constructor-level defaults.
A new cacheThreshold field on the wire schemas carries the resolved
threshold; the cache-bypass header is set when caching is disabled.
Also flags incomplete extractions via a non-enumerable
__extractionIncomplete property so the server-side cache layer can
skip persisting them.
Revives browserbase#1732 by sameelarif.
🦋 Changeset detectedLatest commit: 9b6d859 The changes in this PR will be included in the next version bump. This PR includes changesets to release 5 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 |
|
This PR is from an external contributor and must be approved by a stagehand team member with write access before CI can run. |
There was a problem hiding this comment.
1 issue found across 9 files
Confidence score: 4/5
- This PR looks safe to merge overall; the only noted issue is a release metadata mismatch rather than a runtime/code-path defect.
- The most significant risk is in
.changeset/slow-insects-lie.md: labeling an additive public API change aspatchinstead ofminorcould under-communicate impact to consumers and affect versioning expectations. - Given the issue’s moderate-low severity (4/10) and non-functional scope, merge risk appears minimal if the changeset type is corrected promptly.
- Pay close attention to
.changeset/slow-insects-lie.md- ensure the semver bump reflects the additive API change (minorvspatch).
Architecture diagram
sequenceDiagram
participant Client as SDK Consumer
participant V3 as V3 Engine
participant Resolver as resolveServerCache*
participant API as APIClient
Note over Client,API: NEW: Per-Method Cache Threshold Flow
Client->>V3: stagehand.act("click", { serverCache: { threshold: 10 } })
V3->>Resolver: resolveServerCacheBoolean("act", { threshold: 10 })
Resolver-->>V3: true
V3->>Resolver: resolveServerCacheThreshold("act", { threshold: 10 })
Resolver-->>V3: 10
V3->>API: act({ input, options: { serverCache: true }, cacheThreshold: 10 })
API->>API: Strip serverCache from options, derive cache-bypass header
alt serverCache is object { threshold }
API->>API: Set serverCache = true (caching enabled)
end
API->>API: Include cacheThreshold in request body
API-->>V3: ActResult (with cache metadata)
Note over Client,API: Constructor-Level Per-Method Defaults
Client->>V3: new Stagehand({ serverCache: { act: { threshold: 5 }, extract: false, observe: true } })
V3->>API: Constructor stores config
API-->>V3: APIClient with serverCache=undefined (delegates to per-request)
Client->>V3: stagehand.extract("get user info") // no method-level override
V3->>Resolver: resolveServerCacheBoolean("extract")
alt Constructor config is object
V3->>Resolver: Lookup this.opts.serverCache["extract"] = false
Resolver-->>V3: false (caching disabled)
end
V3->>Resolver: resolveServerCacheThreshold("extract")
Resolver-->>V3: undefined (boolean, no threshold)
Note over V3,API: Extraction Incomplete Marker
API->>API: extract() sends request with cacheThreshold(undefined)
API-->>V3: ExtractResult
V3->>V3: extractHandler runs, process complete
alt Extraction not fully complete
V3->>V3: Mark output with non-enumerable __extractionIncomplete = true
Note right of V3: Prevents caching of partial results
end
Note over Client,API: Priority Resolution (method > constructor > default)
Client->>V3: stagehand.observe("find buttons", { serverCache: false })
V3->>Resolver: resolveServerCacheBoolean("observe", false)
alt Method-level false overrides constructor-level true
Resolver-->>V3: false (bypass cache)
end
V3->>API: observe({ options: { serverCache: false } })
API->>API: Send cache-bypass header, no cacheThreshold
API-->>V3: ObserveResult
Client->>V3: stagehand.act("type text") // no method-level, constructor has threshold object
V3->>Resolver: resolveServerCacheBoolean("act")
alt Constructor serverCache is object, method setting exists
V3->>Resolver: this.opts.serverCache["act"] = { threshold: 5 }
Resolver-->>V3: true (caching enabled)
end
V3->>Resolver: resolveServerCacheThreshold("act")
Resolver-->>V3: 5 (from constructor default)
V3->>API: act({ cacheThreshold: 5 })
Reply with feedback, questions, or to request a fix.
Fix all with cubic | Re-trigger cubic
Per cubic review on browserbase#2155: extending the public serverCache option to accept boolean | { threshold: number } and per-method config objects is an additive surface change, so the semver bump should be minor rather than patch.
What
Extends
serverCacheto acceptboolean | { threshold: number }onact()/extract()/observe()options and on theStagehandconstructor. The constructor additionally accepts a per-method object for fine-grained control:Method-level options take precedence over constructor-level defaults.
How
resolveServerCacheBoolean()+resolveServerCacheThreshold()helpers inV3collapse the constructor + per-call config to aboolean(for the cache-bypass header) and an optionalnumber(for the newcacheThresholdwire field) on each request.ActRequestSchema/ExtractRequestSchema/ObserveRequestSchemagain an optionalcacheThresholdfield; matching entries added topackages/server-v3/openapi.v3.yaml.extractHandlermarks incomplete extractions with a non-enumerable__extractionIncompleteproperty so the server-side cache layer can skip persisting them.APIClientconstructor only receivesserverCachewhen it's a plainboolean— the per-method object form is handled per-request viacacheThreshold.Note
Picks up #1732 by @sameelarif. PR went stale (~3 months) and had conflicts with
mainafter the STG-1182 was added through #1581. Rebased onto currentmainand resolved conflicts so that this PR is purely the threshold layer on top of the already-merged on/off cache toggle.Notable resolutions:
api.ts(suppresses MISS log/surface when caching was bypassed).cache-variables.test.tsandcaching.mdx(both already shipped via [STG-1182] cache config #1581, the PR's older versions would have regressed them).expectTypeOf().toExtend()in theObserveResulttype test (main's pattern). The stricttoEqualTypeOfagainst an intersection type is brittle.Summary by cubic
Add per-method server cache thresholds so you can tune when cached results are returned for
act,extract, andobserve. Implements STG-1427; method-level options override constructor defaults without breaking the on/off toggle.serverCachenow acceptsboolean | { threshold: number }inStagehandand per-method options; the constructor also supports{ act, extract, observe }.cacheThresholdper request; method options take precedence over constructor values.cacheThresholdtoActRequest,ExtractRequest, andObserveRequestschemas and updatedopenapi.v3.yaml; API client logsbrowserbase-cache-statuswhen present.__extractionIncompleteso the server cache skips persisting them.Written for commit 9b6d859. Summary will update on new commits. Review in cubic