mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 19:04:02 +00:00
Merge branch 'main' into upstream/wind-stale
This commit is contained in:
305 files changed
+8508
-1252
No files matched your search
@@ -333,13 +333,20 @@ export const getAircraftTrack = defineTool({
|
||||
requires: ['aircraft'],
|
||||
async run(args, { services, signal }) {
|
||||
const icao24 = args.icao24.toLowerCase();
|
||||
const source = feedFor(services, args.military);
|
||||
// History is optional: the standalone military source has none.
|
||||
if (typeof source.getTrack !== 'function')
|
||||
throw new ToolError(
|
||||
'unsupported',
|
||||
args.military
|
||||
? 'Track history is not available for the military aircraft feed'
|
||||
: 'Track history is not available for the aircraft feed',
|
||||
);
|
||||
// A track server answers 404 for an aircraft it has no positions for.
|
||||
const track = await feedFor(services, args.military)
|
||||
.getTrack(icao24, { signal })
|
||||
.catch((error) => {
|
||||
if (error?.status === 404) return { records: [] };
|
||||
throw error;
|
||||
});
|
||||
const track = await source.getTrack(icao24, { signal }).catch((error) => {
|
||||
if (error?.status === 404) return { records: [] };
|
||||
throw error;
|
||||
});
|
||||
const points = [...track.records].sort(
|
||||
(a, b) => a.observedAtMs - b.observedAtMs,
|
||||
);
|
||||
|
||||
@@ -3,6 +3,8 @@ import test from 'node:test';
|
||||
import { composeCatalog, coreTools } from '../index.js';
|
||||
import { airlineDesignator } from './aviation.js';
|
||||
import { LiveSourceError } from '../../sources/live/contract.js';
|
||||
import { createMcpServer } from '../mcp/index.js';
|
||||
import { createToolServices } from '../services.js';
|
||||
|
||||
const record = (id, latitude, longitude, extra = {}) => ({
|
||||
id,
|
||||
@@ -242,6 +244,61 @@ test('tracks are ordered and thinned to 200 points', async () => {
|
||||
);
|
||||
});
|
||||
|
||||
test('military track history is unsupported by the default composition and kept for custom sources', async () => {
|
||||
const requests = [];
|
||||
const services = createToolServices({
|
||||
fetchImpl: async (url) => {
|
||||
requests.push(String(url));
|
||||
throw new Error('no request expected');
|
||||
},
|
||||
appUrl: 'http://localhost:5173',
|
||||
});
|
||||
const catalog = composeCatalog({ tools: coreTools, services });
|
||||
await assert.rejects(
|
||||
catalog.call('get_aircraft_track', { icao24: 'AE0001', military: true }),
|
||||
(error) =>
|
||||
error.name === 'ToolError' &&
|
||||
error.code === 'unsupported' &&
|
||||
/military/.test(error.message),
|
||||
);
|
||||
const server = createMcpServer({ catalog, name: 'test', version: '1.0.0' });
|
||||
const { result } = await server.handle({
|
||||
jsonrpc: '2.0',
|
||||
id: 1,
|
||||
method: 'tools/call',
|
||||
params: {
|
||||
name: 'get_aircraft_track',
|
||||
arguments: { icao24: 'ae0001', military: true },
|
||||
},
|
||||
});
|
||||
assert.equal(result.isError, true);
|
||||
assert.equal(result.structuredContent.error, 'unsupported');
|
||||
assert.doesNotMatch(result.content[0].text, /try again|later/i);
|
||||
assert.deepEqual(requests, []);
|
||||
|
||||
const track = [
|
||||
{
|
||||
latitude: 37.6,
|
||||
longitude: -122.3,
|
||||
observedAtMs: Date.UTC(2026, 0, 1),
|
||||
baroAltitudeM: 3000,
|
||||
onGround: false,
|
||||
},
|
||||
];
|
||||
const custom = feed(military, { track });
|
||||
const withHistory = composeCatalog({
|
||||
tools: coreTools,
|
||||
services: { aircraft: feed(civil), military: custom },
|
||||
});
|
||||
const kept = await withHistory.call('get_aircraft_track', {
|
||||
icao24: 'AE0001',
|
||||
military: true,
|
||||
});
|
||||
assert.equal(custom.calls[0], 'ae0001');
|
||||
assert.equal(kept.data.total, 1);
|
||||
assert.equal(kept.data.view.follow.kind, 'military_aircraft');
|
||||
});
|
||||
|
||||
test('aircraft info combines type and route lookups', async () => {
|
||||
const aircraft = feed(civil, {
|
||||
enrichment: {
|
||||
|
||||
@@ -55,7 +55,7 @@ const COMPRESS_MIN_BYTES = 1024;
|
||||
* rather than fail; past `PANEL_QUEUED_REQUESTS` waiting, they are refused.
|
||||
*/
|
||||
export const PANEL_CONCURRENT_REQUESTS = 6;
|
||||
export const PANEL_QUEUED_REQUESTS = 256;
|
||||
const PANEL_QUEUED_REQUESTS = 256;
|
||||
|
||||
/**
|
||||
* Each server's panel state: bodies too large for one call, kept for the
|
||||
|
||||
@@ -7,7 +7,7 @@ import { AREA_SCHEMA, resolveArea } from '../area.js';
|
||||
import { cameraForArea, cameraLookingAt } from '../views.js';
|
||||
|
||||
/** Tool arguments that describe a view: an area to frame, or a camera. */
|
||||
export const VIEW_ARGUMENTS = Object.freeze({
|
||||
const VIEW_ARGUMENTS = Object.freeze({
|
||||
view: Object.freeze({
|
||||
type: 'object',
|
||||
description:
|
||||
|
||||
Reference in new issue
Block a user