mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 10:24:02 +00:00
fix: carry weather and fire freshness into tool answers
get_weather dropped the proxy's stale status and get_active_fires dropped FIRMS staleness and failed satellite sources, so answers and the HUD caption read them as current. Both now report them, and the caption context marks such sections stale or degraded.
This commit is contained in:
1 parent
dd8ba562d2
commit
56f0d2e203
4 files changed
+80
-6
No files matched your search
@@ -90,9 +90,11 @@ const AWARENESS_SECTIONS = [
|
||||
function sectionFeedState(section) {
|
||||
if (section.unavailable) return 'unavailable';
|
||||
const data = section.data || {};
|
||||
return data.freshness === 'stale' || data.stale === true
|
||||
? 'stale'
|
||||
: 'nominal';
|
||||
if (data.freshness === 'stale' || data.stale === true) return 'stale';
|
||||
// Answered, but some of the feeds or satellites behind it did not.
|
||||
if (data.missing_sources?.length || data.unavailable_feeds?.length)
|
||||
return 'degraded';
|
||||
return 'nominal';
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -104,9 +104,18 @@ export const getWeather = defineTool({
|
||||
signal,
|
||||
});
|
||||
const row = weatherRow(payload?.weather);
|
||||
// The proxy answers from its cache, marked stale, when a refresh fails.
|
||||
const stale = payload?.status === 'stale';
|
||||
return {
|
||||
summary: `Weather at ${point.label}: ${describeWeather(row)}.`,
|
||||
data: { location: point, weather: row },
|
||||
summary:
|
||||
`Weather at ${point.label}: ${describeWeather(row)}` +
|
||||
(stale ? ' (data may be stale).' : '.'),
|
||||
data: {
|
||||
location: point,
|
||||
weather: row,
|
||||
stale,
|
||||
retrieved_at: payload?.retrievedAt ?? null,
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
@@ -694,3 +694,51 @@ test('a fire perimeter enclosing the whole area is found', async () => {
|
||||
['big'],
|
||||
);
|
||||
});
|
||||
|
||||
test('stale weather and partial fire data reach answers and the HUD caption', async () => {
|
||||
const sent = [];
|
||||
const summary = {
|
||||
async summarize(context) {
|
||||
sent.push(context);
|
||||
return { ok: true, status: 200, data: { summary: 'Austin STALE' } };
|
||||
},
|
||||
};
|
||||
const staleWeather = {
|
||||
getConditions: async () => ({ status: 'stale', weather: conditions }),
|
||||
};
|
||||
const fires = {
|
||||
getSnapshot: async () => ({
|
||||
stale: false,
|
||||
fetchedAt: Date.UTC(2026, 0, 1),
|
||||
sources: [
|
||||
{ source: 'VIIRS_NOAA20_NRT', ok: true },
|
||||
{ source: 'VIIRS_SNPP_NRT', ok: false },
|
||||
],
|
||||
fires: [],
|
||||
}),
|
||||
};
|
||||
const catalog = catalogWith({
|
||||
weather: staleWeather,
|
||||
summary,
|
||||
places,
|
||||
fires,
|
||||
});
|
||||
const weatherResult = await catalog.call('get_weather', {
|
||||
location: { place: 'Austin' },
|
||||
});
|
||||
assert.equal(weatherResult.data.stale, true);
|
||||
assert.match(weatherResult.summary, /\(data may be stale\)\.$/);
|
||||
const fireResult = await catalog.call('get_active_fires', {
|
||||
area: { place: 'Austin' },
|
||||
});
|
||||
assert.deepEqual(fireResult.data.missing_sources, ['VIIRS_SNPP_NRT']);
|
||||
assert.match(fireResult.summary, /\(no data from VIIRS_SNPP_NRT\)\.$/);
|
||||
await catalog.call('get_hud_caption', { area: { place: 'Austin' } });
|
||||
assert.deepEqual(
|
||||
sent[0].enabledLayers.map((layer) => [layer.id, layer.feedState]),
|
||||
[
|
||||
['weather', 'stale'],
|
||||
['fires', 'degraded'],
|
||||
],
|
||||
);
|
||||
});
|
||||
@@ -78,9 +78,24 @@ export const getActiveFires = defineTool({
|
||||
.filter((fire) => areaContains(area, fire))
|
||||
.sort((a, b) => (b.frp ?? 0) - (a.frp ?? 0));
|
||||
const result = capRows(fires, args.limit);
|
||||
// The proxy serves its last good snapshot when a refresh fails, and marks
|
||||
// satellites whose download failed.
|
||||
const stale = snapshot.stale === true;
|
||||
const missing = (snapshot.sources || [])
|
||||
.filter((source) => source?.ok === false)
|
||||
.map((source) => source.source);
|
||||
const notes = [
|
||||
...(stale ? ['data may be stale'] : []),
|
||||
...(missing.length ? [`no data from ${missing.join(', ')}`] : []),
|
||||
];
|
||||
return {
|
||||
summary: `${countNoun(fires.length, 'fire detection')} in ${area.label} in the last 24 hours.`,
|
||||
summary:
|
||||
`${countNoun(fires.length, 'fire detection')} in ${area.label} in the last 24 hours` +
|
||||
(notes.length ? ` (${notes.join('; ')}).` : '.'),
|
||||
data: {
|
||||
stale,
|
||||
missing_sources: missing,
|
||||
fetched_at: isoTime(snapshot.fetchedAt),
|
||||
...result,
|
||||
rows: result.rows.map((fire) => ({
|
||||
lat: fire.lat,
|
||||
|
||||
Reference in new issue
Block a user