UNPKG

@sema-agent/core

Version:

Stateless, task-oriented AI agent core

59 lines (58 loc) • 2.51 kB
export const FLOOR_OUTPUT_TOKENS = 3000; const CONTEXT_HEADROOM_TOKENS = 1000; const CONTEXT_OVERFLOW_RE = /^input length and `max_tokens` exceed context limit: (\d+) \+ (\d+) > (\d+)(?!\w|[.,]\d|\s\d|[+\-*/])/; const CONTEXT_OVERFLOW_PREFIX = "input length and `max_tokens` exceed context limit:"; function providerDiagnostic(body) { const trimmed = body.trim(); if (!trimmed.startsWith("{")) return undefined; let parsed; try { parsed = JSON.parse(trimmed); } catch { return undefined; } if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return undefined; const err = parsed.error; if (typeof err !== "object" || err === null || Array.isArray(err)) return undefined; const message = err.message; return typeof message === "string" ? message : undefined; } function reportFrom(diagnostic) { const message = diagnostic.trimStart(); const m = CONTEXT_OVERFLOW_RE.exec(message); if (m === null) return undefined; if (message.slice(m[0].length).includes(CONTEXT_OVERFLOW_PREFIX)) return undefined; const [, rawInput, rawMax, rawLimit] = m; if (rawInput === undefined || rawMax === undefined || rawLimit === undefined) return undefined; const inputTokens = Number.parseInt(rawInput, 10); const maxTokens = Number.parseInt(rawMax, 10); const contextLimit = Number.parseInt(rawLimit, 10); if (!Number.isSafeInteger(inputTokens) || !Number.isSafeInteger(maxTokens) || !Number.isSafeInteger(contextLimit)) { return undefined; } if (inputTokens <= contextLimit - maxTokens) return undefined; return { inputTokens, maxTokens, contextLimit }; } export function parseContextOverflow(status, body) { if (status !== 400) return undefined; const diagnostic = providerDiagnostic(body); return diagnostic === undefined ? undefined : reportFrom(diagnostic); } export function planOutputCapAdjustment(report, otherCapsInEffect = []) { const available = Math.max(0, report.contextLimit - report.inputTokens - CONTEXT_HEADROOM_TOKENS); if (available < FLOOR_OUTPUT_TOKENS) return { outcome: "below_floor", available }; const current = Math.min(report.maxTokens, ...otherCapsInEffect.filter((c) => c !== undefined)); if (available >= current) return { outcome: "no_progress", available, current }; return { outcome: "adjust", maxOutputTokens: available, current }; }