| 372 | const TOOLS_SYNC_TTL_DISABLE_TOKENS = new Set(["off", "null", "false"]); |
| 373 | |
| 374 | const resolveToolsSyncTtlMs = (): number | null | undefined => { |
| 375 | const raw = process.env.EXECUTOR_TOOLS_SYNC_TTL_MS?.trim(); |
| 376 | if (!raw) return undefined; |
| 377 | if (TOOLS_SYNC_TTL_DISABLE_TOKENS.has(raw.toLowerCase())) return null; |
| 378 | const parsed = Number(raw); |
| 379 | // `isSafeInteger`, not `isInteger`: past 2^53 a decimal literal silently |
| 380 | // rounds to a nearby representable value, so an operator's typo'd digit |
| 381 | // would boot as a TTL they never wrote. Refuse it instead. |
| 382 | if (!Number.isSafeInteger(parsed)) { |
| 383 | // oxlint-disable-next-line executor/no-try-catch-or-throw, executor/no-error-constructor -- boundary: refuse to boot on a malformed operator knob |
| 384 | throw new Error( |
| 385 | `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)`, |
| 386 | ); |
| 387 | } |
| 388 | if (parsed < 0) { |
| 389 | // oxlint-disable-next-line executor/no-try-catch-or-throw, executor/no-error-constructor -- boundary: refuse to boot on a malformed operator knob |
| 390 | throw new Error( |
| 391 | `EXECUTOR_TOOLS_SYNC_TTL_MS ${JSON.stringify(raw)} must not be negative (use "off" to disable time-based re-sync)`, |
| 392 | ); |
| 393 | } |
| 394 | return parsed; |
| 395 | }; |