source dump of claude code
at main 110 lines 4.6 kB view raw
1import { z } from 'zod/v4' 2import { getFeatureValue_CACHED_WITH_REFRESH } from '../services/analytics/growthbook.js' 3import { lazySchema } from '../utils/lazySchema.js' 4import { 5 DEFAULT_POLL_CONFIG, 6 type PollIntervalConfig, 7} from './pollConfigDefaults.js' 8 9// .min(100) on the seek-work intervals restores the old Math.max(..., 100) 10// defense-in-depth floor against fat-fingered GrowthBook values. Unlike a 11// clamp, Zod rejects the whole object on violation — a config with one bad 12// field falls back to DEFAULT_POLL_CONFIG entirely rather than being 13// partially trusted. 14// 15// The at_capacity intervals use a 0-or-≥100 refinement: 0 means "disabled" 16// (heartbeat-only mode), ≥100 is the fat-finger floor. Values 1–99 are 17// rejected so unit confusion (ops thinks seconds, enters 10) doesn't poll 18// every 10ms against the VerifyEnvironmentSecretAuth DB path. 19// 20// The object-level refines require at least one at-capacity liveness 21// mechanism enabled: heartbeat OR the relevant poll interval. Without this, 22// the hb=0, atCapMs=0 drift config (ops disables heartbeat without 23// restoring at_capacity) falls through every throttle site with no sleep — 24// tight-looping /poll at HTTP-round-trip speed. 25const zeroOrAtLeast100 = { 26 message: 'must be 0 (disabled) or ≥100ms', 27} 28const pollIntervalConfigSchema = lazySchema(() => 29 z 30 .object({ 31 poll_interval_ms_not_at_capacity: z.number().int().min(100), 32 // 0 = no at-capacity polling. Independent of heartbeat — both can be 33 // enabled (heartbeat runs, periodically breaks out to poll). 34 poll_interval_ms_at_capacity: z 35 .number() 36 .int() 37 .refine(v => v === 0 || v >= 100, zeroOrAtLeast100), 38 // 0 = disabled; positive value = heartbeat at this interval while at 39 // capacity. Runs alongside at-capacity polling, not instead of it. 40 // Named non_exclusive to distinguish from the old heartbeat_interval_ms 41 // (either-or semantics in pre-#22145 clients). .default(0) so existing 42 // GrowthBook configs without this field parse successfully. 43 non_exclusive_heartbeat_interval_ms: z.number().int().min(0).default(0), 44 // Multisession (bridgeMain.ts) intervals. Defaults match the 45 // single-session values so existing configs without these fields 46 // preserve current behavior. 47 multisession_poll_interval_ms_not_at_capacity: z 48 .number() 49 .int() 50 .min(100) 51 .default( 52 DEFAULT_POLL_CONFIG.multisession_poll_interval_ms_not_at_capacity, 53 ), 54 multisession_poll_interval_ms_partial_capacity: z 55 .number() 56 .int() 57 .min(100) 58 .default( 59 DEFAULT_POLL_CONFIG.multisession_poll_interval_ms_partial_capacity, 60 ), 61 multisession_poll_interval_ms_at_capacity: z 62 .number() 63 .int() 64 .refine(v => v === 0 || v >= 100, zeroOrAtLeast100) 65 .default(DEFAULT_POLL_CONFIG.multisession_poll_interval_ms_at_capacity), 66 // .min(1) matches the server's ge=1 constraint (work_v1.py:230). 67 reclaim_older_than_ms: z.number().int().min(1).default(5000), 68 session_keepalive_interval_v2_ms: z 69 .number() 70 .int() 71 .min(0) 72 .default(120_000), 73 }) 74 .refine( 75 cfg => 76 cfg.non_exclusive_heartbeat_interval_ms > 0 || 77 cfg.poll_interval_ms_at_capacity > 0, 78 { 79 message: 80 'at-capacity liveness requires non_exclusive_heartbeat_interval_ms > 0 or poll_interval_ms_at_capacity > 0', 81 }, 82 ) 83 .refine( 84 cfg => 85 cfg.non_exclusive_heartbeat_interval_ms > 0 || 86 cfg.multisession_poll_interval_ms_at_capacity > 0, 87 { 88 message: 89 'at-capacity liveness requires non_exclusive_heartbeat_interval_ms > 0 or multisession_poll_interval_ms_at_capacity > 0', 90 }, 91 ), 92) 93 94/** 95 * Fetch the bridge poll interval config from GrowthBook with a 5-minute 96 * refresh window. Validates the served JSON against the schema; falls back 97 * to defaults if the flag is absent, malformed, or partially-specified. 98 * 99 * Shared by bridgeMain.ts (standalone) and replBridge.ts (REPL) so ops 100 * can tune both poll rates fleet-wide with a single config push. 101 */ 102export function getPollIntervalConfig(): PollIntervalConfig { 103 const raw = getFeatureValue_CACHED_WITH_REFRESH<unknown>( 104 'tengu_bridge_poll_interval_config', 105 DEFAULT_POLL_CONFIG, 106 5 * 60 * 1000, 107 ) 108 const parsed = pollIntervalConfigSchema().safeParse(raw) 109 return parsed.success ? parsed.data : DEFAULT_POLL_CONFIG 110}