mirror of
https://github.com/morluto/rea.git
synced 2026-11-14 10:43:30 +00:00
rea-agents 6.9.0 advertised `^[^\uD800-\uDFFF]*$` on every local path input. RE2 has no `\u` escape and Rust's `regex`/`jsonschema` crates refuse non-scalar code points, so strict MCP clients and gateways (DeepSeek, RE2 gateways, Open Design) rejected the complete tools request and no REA tool could run. Move the rule into one runtime check, `rejectUnpairedSurrogates`, which advertises nothing and still raises the `invalid_format` regex issue, so CLI and MCP corrections keep reason, expected value, and message. The objdump disassembly symbol already enforced the same rule with its own refinement; it now shares the owner and the correction shape. Dropping the pattern also brings inspect_android_jni_bindings within the compact profile's per-schema budget, so compact delivery now keeps its DEX dimension pattern. The descriptor admission test follows the actual presentation instead of assuming compact always omits it. Fixes #10238 Fixes #10348 Fixes #10198 Co-Authored-By: gensokyo-dev <gensokyo-dev@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
76 lines
3.0 KiB
TypeScript
76 lines
3.0 KiB
TypeScript
import { z } from "zod";
|
|
|
|
/** Portable ASCII identifier starting with a letter. */
|
|
export const IDENTIFIER_PATTERN = /^[A-Za-z][A-Za-z0-9._\x2d]*$/u;
|
|
|
|
/** Stable evidence identifier, also admitting namespace and path separators. */
|
|
export const STABLE_IDENTIFIER_PATTERN = /^[A-Za-z][A-Za-z0-9._:\x2f\x2d]*$/u;
|
|
|
|
// These rules are separate JSON Schema constraints. A single RE2-compatible
|
|
// regex for alphabet and quartet validity requires a repeated alphabet group;
|
|
// V8's Unicode-set engine overflows its regexp stack on that group near the
|
|
// provider's 32 MiB encoded-input budget. Wildcard quartets and literal bad
|
|
// token probes stay stack-safe at that size and compose exactly with `allOf`.
|
|
export const BASE64_QUARTET_LENGTH_PATTERN = /^(?:....)*$/;
|
|
export const INVALID_BASE64_CHARACTER_PATTERN = /[^A-Za-z0-9+\x2f=]/;
|
|
export const INVALID_BASE64_PADDING_PATTERN = /(?:=[^=]|===)/;
|
|
export const INVALID_CANONICAL_BASE64_PAD_BITS_PATTERN =
|
|
/(?:[^AQgw]==$|[BCDFGHJKLNOPRSTVWXZabdefhijlmnpqrtuvxyz1235679+\x2f]=$)/;
|
|
|
|
// In `u` mode a well-formed surrogate pair is one code point outside this
|
|
// range, so the class matches only unpaired surrogates.
|
|
const UNPAIRED_SURROGATE_PATTERN = /[\uD800-\uDFFF]/u;
|
|
|
|
/**
|
|
* Reject unpaired UTF-16 surrogates without advertising a pattern.
|
|
*
|
|
* ECMA-262 spells the surrogate block only as `\uD800-\uDFFF`. RE2 has no `\u`
|
|
* escape and Rust's `regex` and `jsonschema` crates refuse non-scalar code
|
|
* points, and a client that cannot compile one advertised pattern refuses the
|
|
* complete tools request rather than the affected call. The issue keeps the
|
|
* `invalid_format` regex shape an advertised `.regex` raises, so input issue
|
|
* projection still reports `message`.
|
|
*/
|
|
export const rejectUnpairedSurrogates = <Schema extends z.ZodString>(
|
|
schema: Schema,
|
|
message: string,
|
|
): Schema =>
|
|
schema.superRefine((value, context) => {
|
|
if (UNPAIRED_SURROGATE_PATTERN.test(value))
|
|
context.addIssue({
|
|
code: "invalid_format",
|
|
format: "regex",
|
|
message,
|
|
input: value,
|
|
});
|
|
});
|
|
|
|
export const isPaddedBase64 = (value: string): boolean =>
|
|
value.length % 4 === 0 &&
|
|
!INVALID_BASE64_CHARACTER_PATTERN.test(value) &&
|
|
!INVALID_BASE64_PADDING_PATTERN.test(value);
|
|
|
|
export const isCanonicalBase64 = (value: string): boolean =>
|
|
isPaddedBase64(value) &&
|
|
!INVALID_CANONICAL_BASE64_PAD_BITS_PATTERN.test(value);
|
|
|
|
const paddedBase64SchemaRules = [
|
|
{ pattern: BASE64_QUARTET_LENGTH_PATTERN.source },
|
|
{ not: { pattern: INVALID_BASE64_CHARACTER_PATTERN.source } },
|
|
{ not: { pattern: INVALID_BASE64_PADDING_PATTERN.source } },
|
|
];
|
|
|
|
/** Canonical padded base64 with zero pad bits; invalid bytes never enter enclosing range checks. */
|
|
export const canonicalBase64Schema = z
|
|
.string()
|
|
.refine(isCanonicalBase64, {
|
|
message: "Expected canonical padded base64",
|
|
abort: true,
|
|
})
|
|
.meta({
|
|
allOf: [
|
|
...paddedBase64SchemaRules,
|
|
{ not: { pattern: INVALID_CANONICAL_BASE64_PAD_BITS_PATTERN.source } },
|
|
],
|
|
});
|