Merge pull request #1449 from Rohilalala/fix/e-cable-tool-duplicates

fix(tools): list a split submarine cable once in find_submarine_cables
This commit is contained in:
Sameh Khamis authored and GitHub committed 2026-11-01 23:51:06 -08:00
commit 5a2bd8d9f9
4 files changed
+65

No files matched your search

@@ -0,0 +1,3 @@
- List each submarine cable once in find_submarine_cables. TeleGeography
splits 17 cables (2Africa, Echo, Hawaiki) into several features, so a
search for Echo read "3 submarine cables" (Aditya, @Rohilalala, #1449).
+3
View File
@@ -197,6 +197,9 @@ catalog, loaded on first use. See [tools and the MCP server](TOOLS.md).
Aircraft altitude-band queries require a reported barometric or geometric altitude
for each match, so a grounded contact that reports none is left out of a band too.
Queries without an altitude band retain unknown-altitude contacts.
`find_submarine_cables` lists and counts each cable once: TeleGeography splits
a few cables (2Africa, Echo) into several features under one id, and such a
cable matches when any of its parts crosses the area.
Catalog calls check their cancellation signal immediately before executing a
tool. Already-cancelled queries do not start; cancellation after execution starts
+6
View File
@@ -57,6 +57,7 @@ export const findSubmarineCables = defineTool({
Number.isFinite(point.lat) &&
(!area || areaContains(area, point)),
);
const seen = new Set();
const rows = (cables?.features || [])
.filter((feature) => {
const name = String(feature.properties?.name || '');
@@ -71,6 +72,11 @@ export const findSubmarineCables = defineTool({
id: feature.properties.id ?? null,
name: feature.properties.name,
}))
// TeleGeography splits some cables into several features under one id.
.filter((row) => {
const key = row.id ?? row.name;
return !seen.has(key) && seen.add(key);
})
.sort((a, b) => a.name.localeCompare(b.name));
const where = area ? ` in ${area.label}` : '';
const what = wanted ? ` matching "${args.name}"` : '';
+53
View File
@@ -89,6 +89,59 @@ test('cables are found by area and name, with landing points and attribution', a
);
});
test('a cable split into several features is listed once', async () => {
// TeleGeography splits a few cables (2Africa, Echo, Hawaiki) into several
// features under one id.
const cable = (id, name, coordinates) => ({
properties: { id, name },
geometry: { type: 'MultiLineString', coordinates: [coordinates] },
});
const split = {
async fetch() {
return {
cables: {
features: [
cable('2africa', '2Africa', [
[60, 18],
[57, 22],
]),
cable('equiano', 'Equiano', [
[-10, 5],
[3, 6],
]),
cable('2africa', '2Africa', [
[-21, 16],
[-17, 14],
]),
],
},
landingPoints: { features: [] },
};
},
};
const catalog = composeCatalog({
tools: coreTools,
services: { cables: split },
});
const named = await catalog.call('find_submarine_cables', {
name: '2africa',
});
assert.equal(named.summary, '1 submarine cable matching "2africa".');
assert.deepEqual(named.data.rows, [{ id: '2africa', name: '2Africa' }]);
const both = await catalog.call('find_submarine_cables', {
area: { bbox: [-30, 0, 70, 30] },
});
assert.deepEqual(
both.data.rows.map((row) => row.id),
['2africa', 'equiano'],
);
// Only the second part crosses this box; the cable is still found.
const west = await catalog.call('find_submarine_cables', {
area: { bbox: [-25, 10, -10, 20] },
});
assert.deepEqual(west.data.rows, [{ id: '2africa', name: '2Africa' }]);
});
test('the local fetch serves bundled data files and nothing outside them', async () => {
const fetchImpl = createApiFetch({
apiBase: 'http://127.0.0.1:1',