The text_match.py module#

Summary#

edit_distance_le_one

Return True iff Levenshtein distance between a and b is at most 1.

fuzzy_normalize

Normalize value to a canonical spelling from allowed.

sanitize_named_object_key

Return (sanitized_name, notice_or_None) for a NamedObject key.

Description#

Shared string-matching utilities for fuzzy/typo-tolerant lookup.

These helpers are used everywhere the agent has to reconcile an LLM-supplied identifier against a finite, authoritative set of known strings — material names, allowed values of an enum-typed setting, NamedObject keys, dict-key schemas, command kwargs, etc.

Keeping the implementation in one place avoids the trap we hit historically: _check_value learned to tolerate the LLM’s "least-squares-cell-based""least-square-cell-based" typo while copy_material could not even resolve "water-vapour""water-vapor". Both are the same single-edit problem; both should share the same solution.

Public API:

Module detail#

text_match.edit_distance_le_one(a: str, b: str) bool#

Return True iff Levenshtein distance between a and b is at most 1.

Faster than computing the full distance because we only need the 1 verdict.

Parameters:
astr

A supplied to the function.

bstr

B supplied to the function.

Returns:
bool

Boolean result produced by the function.

text_match.fuzzy_normalize(value: str, allowed: collections.abc.Iterable[str]) str | None#

Normalize value to a canonical spelling from allowed.

It returns the canonical spelling for value if exactly one entry in allowed is within edit distance 1 (case-insensitive), else None.

Uniqueness is required so a near-spelling never silently overwrites a value when two candidates are equally plausible — surface the ambiguity to the caller instead.

Parameters:
valuestr

Value supplied to the function.

allowedIterable[str]

Allowed supplied to the function.

Returns:
str | None

String result produced by the function.

text_match.sanitize_named_object_key(name: str, *, replacement: str = '-') tuple[str, str | None]#

Return (sanitized_name, notice_or_None) for a NamedObject key.

Some backends reject whitespace in NamedObject instance keys (BC names, cell-zone names, material names, named-expression keys, …). Internal whitespace runs are collapsed to replacement (hyphen by default — the idiomatic separator, e.g. pressure-outlet-1, phase-1, cold-inlet) and leading or trailing whitespace is stripped.

The function is conservative — it ONLY rewrites whitespace. Other illegal characters (/, \\, :, brackets, …) are rare in natural-language intent and are deliberately left alone so a deterministic rewrite never corrupts a name the user intentionally typed; the backend surfaces those at apply time.

Returns a 2-tuple:

  • sanitized_name — the cleaned name (equal to name when no rewrite was needed).

  • notice — a one-line human-readable explanation of the rewrite, or None when the input was already clean.

Non-string inputs are returned unchanged with notice=None so callers can pipe values through this helper unconditionally.

Example:

>>> sanitize_named_object_key("oil inlet")
('oil-inlet', "name 'oil inlet' contained whitespace; ...")
>>> sanitize_named_object_key("phase-1")
('phase-1', None)
Parameters:
namestr

Name of the object, module, or setting being processed.

replacementstr

Replacement supplied to the function.

Returns:
tuple[str, str | None]

Collection containing the operation results.