Skip to content
中文

Fragment validation and budget rejection ​

The policy implementation follows.

ts
export function validateContextFragment(
  fragment: ContextFragment,
  ids: Set<string> = new Set(),
  checkBudget = true,
): string {
  // Ids are stable keys in usage records and protected-context errors, so they start with a
  // lowercase letter and admit only characters that are safe in both positions.
  if (
    !/^[a-z][a-zA-Z0-9:._-]*$/.test(fragment.id) ||
    ids.has(fragment.id) ||
    !fragment.sourceId ||
    !['instruction', 'server', 'user', 'tool'].includes(fragment.trust) ||
    !['configuration', 'turn', 'step'].includes(fragment.lifetime) ||
    !['system', 'user'].includes(fragment.role) ||
    !Number.isSafeInteger(fragment.maxChars) ||
    fragment.maxChars < 1
  )
    throw new Error('Invalid context fragment');
  // Consumed before the later checks: a failed fragment must not leave its id reusable by a
  // retry through the same accumulator.
  ids.add(fragment.id);
  if (
    fragment.role === 'system' &&
    (fragment.trust === 'user' || fragment.trust === 'tool' || typeof fragment.value !== 'string')
  )
    throw new Error('Untrusted context cannot become a system instruction');
  if (
    typeof fragment.value !== 'string' &&
    (!fragment.value || typeof fragment.value !== 'object' || Array.isArray(fragment.value))
  )
    throw new Error('Invalid context value');
  // Structured values are measured as the JSON text that will be sent, so the declared budget
  // describes the payload rather than the in-memory object.
  const serialized =
    typeof fragment.value === 'string' ? fragment.value : JSON.stringify(fragment.value);
  if (checkBudget && serialized.length > fragment.maxChars)
    throw new ValidationError([
      {
        code: 'CONTEXT_BUDGET',
        message: `上下文片段 ${fragment.id} 超过预算;不截断原问题、约束与证据。`,
      },
    ]);
  return serialized;
}

export function validateContextBudget(
  inputChars: number,
  maxInputChars: number,
  exceeded?: (limit: number) => Error,
): void {
  breakWhile(
    !Number.isSafeInteger(inputChars) || inputChars < 0,
    () => new TypeError('Invalid context input size'),
  );
  breakWhile(
    maxInputChars !== Infinity && (!Number.isSafeInteger(maxInputChars) || maxInputChars < 0),
    () => new TypeError('Invalid context budget'),
  );
  if (inputChars > maxInputChars)
    throw (
      exceeded?.(maxInputChars) ??
      new ValidationError([
        { code: 'CONTEXT_BUDGET', message: `Model input exceeds ${maxInputChars} characters` },
      ])
    );
}

API reference, usage examples and developer guides.