/** * Limits enforcement for workflow source and results. */ import { MAX_SOURCE_BYTES, MAX_RESULT_BYTES } from "./types.ts"; export interface LimitCheckResult { ok: boolean; reason?: string; } /** * Check that a workflow script does not exceed the source size limit. */ export function checkSourceLimit(source: string): LimitCheckResult { const bytes = Buffer.byteLength(source, "utf-8"); if (bytes > MAX_SOURCE_BYTES) { return { ok: false, reason: `Workflow script is ${bytes} bytes; maximum is ${MAX_SOURCE_BYTES} bytes.`, }; } return { ok: true }; } /** * Truncate a step result to the max result bytes limit. * Returns the truncated string and whether truncation occurred. */ export function enforceResultLimit( output: string, maxBytes: number = MAX_RESULT_BYTES, ): { text: string; truncated: boolean } { const bytes = Buffer.byteLength(output, "utf-8"); if (bytes <= maxBytes) return { text: output, truncated: false }; // Truncate to byte limit, keeping valid UTF-8 at the boundary const buf = Buffer.from(output, "utf-8"); let truncated = buf.subarray(0, maxBytes); // Walk back to last complete UTF-8 sequence while (truncated.length > 0) { try { const text = truncated.toString("utf-8"); return { text: `${text}\n\n[Output truncated: ${bytes - Buffer.byteLength(text, "utf-8")} bytes omitted]`, truncated: true, }; } catch { truncated = truncated.subarray(0, truncated.length - 1); } } return { text: "[Output truncated]", truncated: true, }; } /** * Validate that all limits are satisfied for a workflow execution request. */ export function validateLimits(script: string): LimitCheckResult { const sourceCheck = checkSourceLimit(script); if (!sourceCheck.ok) return sourceCheck; return { ok: true }; }