MCPcopy Index your code
hub / github.com/codeaashu/claude-code / processRemoteEvalPayload

Function processRemoteEvalPayload

src/services/analytics/growthbook.ts:327–394  ·  view source on GitHub ↗

* Process a remote eval payload from the GrowthBook server and populate * local caches. Called after both initial client.init() and after * client.refreshFeatures() so that _BLOCKS_ON_INIT callers see fresh values * across the process lifetime, not just init-time snapshots. * * Without this run

(
  gbClient: GrowthBook,
)

Source from the content-addressed store, hash-verified

325 * kill switch for long-running sessions.
326 */
327async function processRemoteEvalPayload(
328 gbClient: GrowthBook,
329): Promise<boolean> {
330 // WORKAROUND: Transform remote eval response format
331 // The API returns { "value": ... } but SDK expects { "defaultValue": ... }
332 // TODO: Remove this once the API is fixed to return correct format
333 const payload = gbClient.getPayload()
334 // Empty object is truthy — without the length check, `{features: {}}`
335 // (transient server bug, truncated response) would pass, clear the maps
336 // below, return true, and syncRemoteEvalToDisk would wholesale-write `{}`
337 // to disk: total flag blackout for every process sharing ~/.claude.json.
338 if (!payload?.features || Object.keys(payload.features).length === 0) {
339 return false
340 }
341
342 // Clear before rebuild so features removed between refreshes don't
343 // leave stale ghost entries that short-circuit getFeatureValueInternal.
344 experimentDataByFeature.clear()
345
346 const transformedFeatures: Record<string, MalformedFeatureDefinition> = {}
347 for (const [key, feature] of Object.entries(payload.features)) {
348 const f = feature as MalformedFeatureDefinition
349 if ('value' in f && !('defaultValue' in f)) {
350 transformedFeatures[key] = {
351 ...f,
352 defaultValue: f.value,
353 }
354 } else {
355 transformedFeatures[key] = f
356 }
357
358 // Store experiment data for later logging when feature is accessed
359 if (f.source === 'experiment' && f.experimentResult) {
360 const expResult = f.experimentResult as {
361 variationId?: number
362 }
363 const exp = f.experiment as { key?: string } | undefined
364 if (exp?.key && expResult.variationId !== undefined) {
365 experimentDataByFeature.set(key, {
366 experimentId: exp.key,
367 variationId: expResult.variationId,
368 })
369 }
370 }
371 }
372 // Re-set the payload with transformed features
373 await gbClient.setPayload({
374 ...payload,
375 features: transformedFeatures,
376 })
377
378 // WORKAROUND: Cache the evaluated values directly from remote eval response.
379 // The SDK's evalFeature() tries to re-evaluate rules locally, ignoring the
380 // pre-evaluated 'value' from remoteEval. setForcedFeatures also doesn't work
381 // reliably. So we cache values ourselves and use them in getFeatureValueInternal.
382 remoteEvalFeatureValues.clear()
383 for (const [key, feature] of Object.entries(transformedFeatures)) {
384 // Under remoteEval:true the server pre-evaluates. Whether the answer

Callers 2

growthbook.tsFile · 0.85

Calls 4

keysMethod · 0.80
entriesMethod · 0.80
clearMethod · 0.45
setMethod · 0.45

Tested by

no test coverage detected