@geometra/mcp 1.43.0 → 1.44.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/server.js +57 -1
- package/dist/session.js +19 -5
- package/package.json +1 -1
package/dist/server.js
CHANGED
|
@@ -3546,6 +3546,62 @@ function suggestRecovery(field, error) {
|
|
|
3546
3546
|
}
|
|
3547
3547
|
return undefined;
|
|
3548
3548
|
}
|
|
3549
|
+
// Normalize a value for verifyFills comparison so caller-friendly inputs
|
|
3550
|
+
// match site-formatted readbacks. The legacy comparison was strict lowercase
|
|
3551
|
+
// only — which broke every form that auto-formats phone numbers, dates, or
|
|
3552
|
+
// currency fields. Greenhouse turns "+1-929-608-1737" into "(929) 608-1737";
|
|
3553
|
+
// Workday turns "$160000" into "$160,000.00"; Lever turns "2026-01-01" into
|
|
3554
|
+
// "01/01/2026". The lowercase comparator flagged all of these as mismatches
|
|
3555
|
+
// even though the field state was correct, forcing every caller to either
|
|
3556
|
+
// disable verifyFills or wrap it in defensive try/catch.
|
|
3557
|
+
//
|
|
3558
|
+
// The fix: detect phone-like and number-like values and compare on the
|
|
3559
|
+
// canonical digit sequence. Plain text and short strings still go through
|
|
3560
|
+
// the strict lowercase comparator so unrelated content can't accidentally
|
|
3561
|
+
// match (e.g. "1234 Main St" vs "12-34 Main").
|
|
3562
|
+
function looksLikePhoneNumber(value) {
|
|
3563
|
+
// Heuristic: at least 7 digits, and after stripping whitespace + the
|
|
3564
|
+
// common phone separator characters (+ - . ( ) space ext) only digits
|
|
3565
|
+
// and a single optional leading + remain. Catches international and
|
|
3566
|
+
// domestic formats without false-matching addresses or IDs.
|
|
3567
|
+
const stripped = value.replace(/[\s().\-+x]|ext\.?/gi, '');
|
|
3568
|
+
if (stripped.length < 7)
|
|
3569
|
+
return false;
|
|
3570
|
+
if (!/^\d+$/.test(stripped))
|
|
3571
|
+
return false;
|
|
3572
|
+
return /\d.*[\s().\-+]|^\+\d/.test(value) || /^\d{7,}$/.test(value);
|
|
3573
|
+
}
|
|
3574
|
+
function looksLikeFormattedNumber(value) {
|
|
3575
|
+
// Catches "$160,000.00" / "1,000,000" / "1.5e6" style readbacks where the
|
|
3576
|
+
// site adds thousands separators or currency prefixes. Requires at least
|
|
3577
|
+
// one comma OR currency prefix to avoid matching plain text.
|
|
3578
|
+
if (!/[$€£¥,]/.test(value))
|
|
3579
|
+
return false;
|
|
3580
|
+
return /\d/.test(value);
|
|
3581
|
+
}
|
|
3582
|
+
function digitSignature(value) {
|
|
3583
|
+
return value.replace(/\D+/g, '');
|
|
3584
|
+
}
|
|
3585
|
+
function valuesEquivalent(expected, actual) {
|
|
3586
|
+
if (expected.toLowerCase() === actual.toLowerCase())
|
|
3587
|
+
return true;
|
|
3588
|
+
// Both look like phones → compare digit signatures only
|
|
3589
|
+
if (looksLikePhoneNumber(expected) && looksLikePhoneNumber(actual)) {
|
|
3590
|
+
return digitSignature(expected) === digitSignature(actual);
|
|
3591
|
+
}
|
|
3592
|
+
// Both look like formatted numbers → compare digit signatures only
|
|
3593
|
+
if (looksLikeFormattedNumber(expected) || looksLikeFormattedNumber(actual)) {
|
|
3594
|
+
const eDigits = digitSignature(expected);
|
|
3595
|
+
const aDigits = digitSignature(actual);
|
|
3596
|
+
if (eDigits && aDigits && eDigits === aDigits)
|
|
3597
|
+
return true;
|
|
3598
|
+
}
|
|
3599
|
+
// Whitespace normalization for everything else (handles "Charlie Greenman"
|
|
3600
|
+
// vs "Charlie Greenman" auto-collapsed by ATS forms)
|
|
3601
|
+
const eNorm = expected.replace(/\s+/g, ' ').trim().toLowerCase();
|
|
3602
|
+
const aNorm = actual.replace(/\s+/g, ' ').trim().toLowerCase();
|
|
3603
|
+
return eNorm === aNorm;
|
|
3604
|
+
}
|
|
3549
3605
|
function verifyFormFills(session, planned) {
|
|
3550
3606
|
const a11y = sessionA11y(session);
|
|
3551
3607
|
if (!a11y)
|
|
@@ -3566,7 +3622,7 @@ function verifyFormFills(session, planned) {
|
|
|
3566
3622
|
if (!actual || !expected) {
|
|
3567
3623
|
mismatches.push({ fieldLabel: label, expected, actual, ...(p.field.fieldId ? { fieldId: p.field.fieldId } : {}) });
|
|
3568
3624
|
}
|
|
3569
|
-
else if (
|
|
3625
|
+
else if (!valuesEquivalent(expected, actual)) {
|
|
3570
3626
|
mismatches.push({ fieldLabel: label, expected, actual, ...(p.field.fieldId ? { fieldId: p.field.fieldId } : {}) });
|
|
3571
3627
|
}
|
|
3572
3628
|
else {
|
package/dist/session.js
CHANGED
|
@@ -1782,12 +1782,26 @@ function compactSchemaContext(context, label) {
|
|
|
1782
1782
|
return Object.keys(out).length > 0 ? out : undefined;
|
|
1783
1783
|
}
|
|
1784
1784
|
function compactSchemaValue(value, inlineLimit = 80) {
|
|
1785
|
-
|
|
1786
|
-
|
|
1785
|
+
// Measure the length of the FULL whitespace-normalized value first, before
|
|
1786
|
+
// any inline truncation. The previous implementation called sanitizeInlineName
|
|
1787
|
+
// with max=120 and then read normalized.length, which capped reported length
|
|
1788
|
+
// at 120 even when the actual filled content was 1000+ characters. That made
|
|
1789
|
+
// form-required snapshots look like long-textarea fills had only landed
|
|
1790
|
+
// ~120 chars, when in reality the field was correctly filled — agents then
|
|
1791
|
+
// re-typed the same content thinking they had a partial fill, doubling the
|
|
1792
|
+
// value or hitting the textarea length cap.
|
|
1793
|
+
if (!value)
|
|
1794
|
+
return {};
|
|
1795
|
+
const fullNormalized = normalizeUiText(value);
|
|
1796
|
+
if (!fullNormalized)
|
|
1787
1797
|
return {};
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1798
|
+
const fullLength = fullNormalized.length;
|
|
1799
|
+
const inlineNormalized = sanitizeInlineName(value, Math.max(120, inlineLimit + 32));
|
|
1800
|
+
if (!inlineNormalized)
|
|
1801
|
+
return { valueLength: fullLength };
|
|
1802
|
+
return fullLength <= inlineLimit
|
|
1803
|
+
? { value: inlineNormalized }
|
|
1804
|
+
: { valueLength: fullLength };
|
|
1791
1805
|
}
|
|
1792
1806
|
function schemaOptionLabel(node) {
|
|
1793
1807
|
return sanitizeFieldName(node.name, 80) ?? sanitizeInlineName(node.name, 80);
|
package/package.json
CHANGED