| 293 | const TOOLS_SYNC_TTL_DISABLE_TOKENS = new Set(["off", "null", "false"]); |
| 294 | |
| 295 | const resolveToolsSyncTtlMs = (): number | null | undefined => { |
| 296 | const raw = process.env.EXECUTOR_TOOLS_SYNC_TTL_MS?.trim(); |
| 297 | if (!raw) return undefined; |
| 298 | if (TOOLS_SYNC_TTL_DISABLE_TOKENS.has(raw.toLowerCase())) return null; |
| 299 | const parsed = Number(raw); |
| 300 | // `isSafeInteger`, not `isInteger`: past 2^53 a decimal literal silently |
| 301 | // rounds to a nearby representable value, so an operator's typo'd digit |
| 302 | // would boot as a TTL they never wrote. Refuse it instead. |
| 303 | if (!Number.isSafeInteger(parsed)) { |
| 304 | // oxlint-disable-next-line executor/no-try-catch-or-throw, executor/no-error-constructor -- boundary: refuse to boot on a malformed operator knob |
| 305 | throw new Error( |
| 306 | `EXECUTOR_TOOLS_SYNC_TTL_MS ${JSON.stringify(raw)} is not an exactly representable whole number of milliseconds ("off", "null" or "false" disable time-based re-sync)`, |
| 307 | ); |
| 308 | } |
| 309 | if (parsed < 0) { |
| 310 | // oxlint-disable-next-line executor/no-try-catch-or-throw, executor/no-error-constructor -- boundary: refuse to boot on a malformed operator knob |
| 311 | throw new Error( |
| 312 | `EXECUTOR_TOOLS_SYNC_TTL_MS ${JSON.stringify(raw)} must not be negative (use "off" to disable time-based re-sync)`, |
| 313 | ); |
| 314 | } |
| 315 | return parsed; |
| 316 | }; |