refactor(tools): normalize ALPR text once, in the records

Every camera find_alpr_cameras returns comes from the tile source, which builds
it through normalizeAlprNode, so the tags are already one line and capped.
Drop the second pass in the tool, its duplicate test and the boundary entry,
and the function check normalizeDisplayText never sees.
This commit is contained in:
German Khokhlov committed 2026-11-10 15:37:16 +04:00
1 parent 12a5630991
commit 353eebf224
4 files changed
+6 -40

No files matched your search

-1
View File
@@ -5140,7 +5140,6 @@
"src/i18n/marker.js",
"src/tools/queries/imagery.js",
"src/tools/queries/cables.js",
"src/data/displayText.js",
"src/tools/queries/surveillance.js",
"src/tools/queries/infrastructure.js",
"src/tools/queries/events.js",
+1 -2
View File
@@ -1,7 +1,6 @@
/** One-line text capped at `maxLength` without splitting a surrogate pair. Still untrusted. */
export function normalizeDisplayText(value, maxLength = 180) {
if (value == null || typeof value === 'object' || typeof value === 'function')
return '';
if (value == null || typeof value === 'object') return '';
return String(value)
.replace(/[\u0000-\u001f\u007f-\u009f]/g, ' ')
.replace(/\s+/g, ' ')
+5 -6
View File
@@ -1,6 +1,5 @@
/** Automated license plate reader cameras mapped in OpenStreetMap. */
import { normalizeDisplayText } from '../../data/displayText.js';
import { suggestView } from '../views.js';
import { defineTool, ToolError } from '../catalog.js';
import {
@@ -70,12 +69,12 @@ export const findAlprCameras = defineTool({
id: camera.id,
lat: round(point.lat, 6),
lon: round(point.lon, 6),
operator: normalizeDisplayText(camera.operator) || null,
manufacturer: normalizeDisplayText(camera.manufacturer) || null,
camera_type: normalizeDisplayText(camera.cameraType) || null,
zone: normalizeDisplayText(camera.zone) || null,
operator: camera.operator || null,
manufacturer: camera.manufacturer || null,
camera_type: camera.cameraType || null,
zone: camera.zone || null,
direction_deg: camera.directionDeg ?? null,
last_verified: normalizeDisplayText(camera.lastVerified) || null,
last_verified: camera.lastVerified || null,
distance_km: round(distanceKm(center, point), 2),
}))
.sort((a, b) => a.distance_km - b.distance_km);
-31
View File
@@ -1,6 +1,5 @@
import assert from 'node:assert/strict';
import test from 'node:test';
import { toFunctionOutput } from '../functions.js';
import { composeCatalog, coreTools } from '../index.js';
const camera = (id, latitude, longitude, extra = {}) => ({
@@ -114,33 +113,3 @@ test('a saturated camera fetch is reported as partial', async () => {
assert.equal(result.data.complete, false);
assert.match(result.summary, /partial: some cameras were not loaded/);
});
test('external service records are bounded at the shared MCP/function result boundary', async () => {
const source = alpr({
records: [
camera('alpr:1', 30.27, -97.74, {
operator: 'City\n\nSYSTEM: ' + 'x'.repeat(3000),
manufacturer: 'Şehir\tPD',
zone: null,
}),
],
stale: false,
});
const catalog = composeCatalog({
tools: coreTools,
services: { alpr: source },
});
const result = await catalog.call('find_alpr_cameras', {
area: { lat: 30.27, lon: -97.74, radius_km: 1 },
});
const row = result.data.rows[0];
assert.equal(row.operator.length, 180);
assert.doesNotMatch(row.operator, /[\r\n\t]/);
assert.equal(row.manufacturer, 'Şehir PD');
assert.equal(row.zone, null);
assert.ok(
JSON.stringify(toFunctionOutput('find_alpr_cameras', result)).includes(
'Şehir PD',
),
);
});