mirror of
https://github.com/stablyai/orca.git
synced 2026-09-22 16:02:32 +00:00
parsePositiveSafeIntegerNumericText mirrors the CLI's own Number() coercion on purpose: text like `600000.000000000000001` is the budget the CLI will actually wait on, so rejecting it here would leave the relay and SSH kill timers shorter than the CLI's and cut the request short. Document that and pin it with regression cases.
60 lines
2.0 KiB
TypeScript
60 lines
2.0 KiB
TypeScript
export const MAX_TIMER_DELAY_MS = 2_147_483_647
|
|
|
|
export function isSafeTimerDelayMs(value: unknown): value is number {
|
|
return (
|
|
typeof value === 'number' &&
|
|
Number.isSafeInteger(value) &&
|
|
value >= 0 &&
|
|
value <= MAX_TIMER_DELAY_MS
|
|
)
|
|
}
|
|
|
|
export function parsePositiveSafeIntegerText(raw: string): number | null {
|
|
const trimmed = raw.trim()
|
|
const value = Number(trimmed)
|
|
if (!Number.isSafeInteger(value) || value <= 0) {
|
|
return null
|
|
}
|
|
const exactValue = parseExactIntegerNumericText(trimmed)
|
|
return exactValue === BigInt(value) ? value : null
|
|
}
|
|
|
|
// Why: mirrors the CLI's own `Number()` coercion for generic `--timeout-ms`
|
|
// flags (cli/flags.ts getOptionalPositiveIntegerFlag). Text that coerces to an
|
|
// exact integer — `1000.0`, `600000.000000000000001` — is the budget the CLI
|
|
// will actually wait on, so rejecting it here would leave the caller's timer
|
|
// shorter than the CLI's and cut the request short. Callers that need exact
|
|
// text (orchestration ask) use parsePositiveSafeIntegerText instead.
|
|
export function parsePositiveSafeIntegerNumericText(raw: string): number | null {
|
|
const value = Number(raw)
|
|
return Number.isSafeInteger(value) && value > 0 ? value : null
|
|
}
|
|
|
|
function parseExactIntegerNumericText(raw: string): bigint | null {
|
|
if (
|
|
/^\+?0[xX][\da-fA-F]+$/.test(raw) ||
|
|
/^\+?0[bB][01]+$/.test(raw) ||
|
|
/^\+?0[oO][0-7]+$/.test(raw)
|
|
) {
|
|
return BigInt(raw.startsWith('+') ? raw.slice(1) : raw)
|
|
}
|
|
const match = /^\+?(\d+(?:\.\d*)?|\.\d+)(?:[eE]([+-]?\d+))?$/.exec(raw)
|
|
if (!match) {
|
|
return null
|
|
}
|
|
const [whole = '', fraction = ''] = match[1].split('.')
|
|
const digits = `${whole}${fraction}`.replace(/^0+/, '') || '0'
|
|
const shift = Number(match[2] ?? 0) - fraction.length
|
|
if (!Number.isSafeInteger(shift)) {
|
|
return null
|
|
}
|
|
if (shift >= 0) {
|
|
return BigInt(digits) * 10n ** BigInt(shift)
|
|
}
|
|
const removedDigits = -shift
|
|
if (removedDigits > digits.length || !digits.endsWith('0'.repeat(removedDigits))) {
|
|
return null
|
|
}
|
|
return BigInt(digits.slice(0, -removedDigits) || '0')
|
|
}
|