Merge branch 'main' of https://github.com/bilawalsidhu/gods-eye-view into fix/cctv-tool-routing

This commit is contained in:
manjunath committed 2026-10-19 21:12:55 +05:30
commit a6f229d870
12 files changed
+784 -165

No files matched your search

+12 -159
View File
@@ -1,6 +1,5 @@
import {
layerSnapshot,
layerSnapshots,
feedProvenanceEnvelope,
} from '../data/layerSnapshot.js';
import { readLayerLifecycleSummary } from './layerSummary.js';
@@ -27,7 +26,6 @@ import {
isContextRecordActive,
} from '../data/contextStore.js';
import { CCTV_FOCUS_RESULT } from '../layers/cctv/index.js';
import { contextModeWord } from '../contextModePolicy.js';
import {
createAnalystEngine,
normalizeAnalystSpec,
@@ -48,6 +46,12 @@ import { unavailablePlaceSearch } from '../search/placeSearch.js';
import * as defaultAnnotationResolver from '../annotations/annotationResolver.js';
import { normalizeRadioCountryInput } from '../data/radioCountry.js';
import { TR3B_CLASS } from '../data/tr3bRegistry.js';
import {
getWorldPacket,
withContextModeVocabulary,
activeContactsWindow,
TRACKABLE_FAMILIES,
} from '../agent/worldPacket.js';
const ALLOWED_STYLES = new Set([
'normal',
@@ -119,64 +123,6 @@ const CONTEXT_MODE_ALIASES = new Map([
['space-missions', 'space-missions'],
['missions', 'space-missions'],
]);
/**
* Every model-readable field that carries a context-mode id, and what an
* absent value means for each.
*
* `mode` always names a mode, so nothing is 'off'. `entering` and `priorMode`
* are absent when there is no such mode at all — calling those 'off' would
* assert a state that does not exist.
*/
const CONTEXT_MODE_RESULT_FIELDS = Object.freeze([
{ field: 'mode', emptyAs: 'off' },
{ field: 'entering', emptyAs: null },
{ field: 'priorMode', emptyAs: null },
]);
/** Nested results that are themselves context-mode payloads the model reads. */
const NESTED_CONTEXT_RESULT_FIELDS = Object.freeze([
'context',
'contextRollback',
]);
/**
* Report a context-mode payload in the tools' own vocabulary.
*
* `set_context_mode` accepts 'contacts' while the mode's internal id is
* 'flights'. Reporting the internal id back made the model read
* `mode:'flights'` as "Contacts is off" and refuse to answer from the Contacts
* window counts sitting in the very same payload (owner field session
* 2026-08-21). Secondary fields and nested transition/rollback results are
* translated too — one leaked internal id is enough to recreate the confusion,
* and a rollback result is exactly what the model reads when something went
* wrong. Each internal id is kept alongside as `<field>Internal` for anything
* reasoning about layers.
* @param {object|null|undefined} state Any payload carrying context-mode fields.
* @returns {object|null|undefined} The same payload, modes translated.
*/
function withContextModeVocabulary(state) {
if (!state || typeof state !== 'object') return state;
let out = state;
const mutable = () => {
if (out === state) out = { ...state };
return out;
};
for (const { field, emptyAs } of CONTEXT_MODE_RESULT_FIELDS) {
if (!(field in state)) continue;
const internal = state[field] ?? null;
const target = mutable();
target[field] = contextModeWord(internal, { emptyAs });
target[`${field}Internal`] = internal;
}
for (const field of NESTED_CONTEXT_RESULT_FIELDS) {
const nested = state[field];
if (!nested || typeof nested !== 'object') continue;
const translated = withContextModeVocabulary(nested);
if (translated !== nested) mutable()[field] = translated;
}
return out;
}
const COCKPIT_ACTION_ALIASES = new Map([
['next', 'next'],
['previous', 'previous'],
@@ -246,14 +192,6 @@ const STACK_ALIASES = new Map([
['road map', 'osm'],
]);
/** Search order for track_entity across entity layer families. */
const TRACKABLE_FAMILIES = [
{ layerId: 'flights', kind: 'aircraft' },
{ layerId: 'military', kind: 'aircraft' },
{ layerId: 'ais-live-vessels', kind: 'vessel' },
{ layerId: 'satellites', kind: 'satellite' },
];
const FRAME_TARGETS = new Map([
['flights', 'flights'],
['planes', 'flights'],
@@ -2565,26 +2503,6 @@ function runManagedVoiceNavigation(
};
}
/** Gathers tracked/selected entities across layer families for read-back. */
function collectTrackedEntities(dataManager) {
const tracked = [];
for (const family of TRACKABLE_FAMILIES) {
const module = dataManager.layers.get(family.layerId)?.module;
if (!module) continue;
try {
const info =
family.kind === 'vessel'
? module.getSelectedInfo?.()
: module.getTrackedInfo?.();
if (info)
tracked.push({ kind: family.kind, layerId: family.layerId, ...info });
} catch {
// layer not ready
}
}
return tracked;
}
export async function getBasemapLabelContext(
viewer,
service = defaultGeospatial,
@@ -3222,60 +3140,12 @@ function getCurrentViewState(
dataManager,
sceneDirector = null,
) {
const cartographic = Cesium.Cartographic.fromCartesian(
viewer.camera.positionWC,
);
return {
ok: true,
action: 'get_current_view_state',
camera: {
latitude: Cesium.Math.toDegrees(cartographic.latitude),
longitude: Cesium.Math.toDegrees(cartographic.longitude),
heightM: cartographic.height,
},
style: styleManager.activeStyle || 'normal',
context:
typeof styleManager.getContextModeState === 'function'
? {
...withContextModeVocabulary(styleManager.getContextModeState()),
// The numbers on the operator's Contacts panel, so a window/count
// question can be answered from what they are looking at.
...(activeContactsWindow(dataManager)
? { contactsWindow: activeContactsWindow(dataManager) }
: {}),
}
: null,
cockpit:
typeof styleManager.getCockpitState === 'function'
? styleManager.getCockpitState()
: null,
controls:
typeof styleManager.getControlState === 'function'
? styleManager.getControlState()
: null,
scenePlayback: sceneDirector?.getPlaybackStatus?.() || null,
tracked: collectTrackedEntities(dataManager),
// Enabled layers only: the full registry cost ~1k tokens per call and
// the model only reasons about what is on.
disabledLayerCount: dataManager.getAll().filter((layer) => !layer.enabled)
.length,
layers: dataManager
.getAll()
.filter((layer) => layer.enabled)
.map((layer) => ({
id: layer.id,
name: layer.name,
enabled: layer.enabled,
count: layer.stats?.count || 0,
error: layer.stats?.error || null,
feedState: layerSnapshot(layer).feedState,
source: layerSnapshot(layer).source,
lastUpdate: layerSnapshot(layer).lastUpdate,
})),
feedProvenance: feedProvenanceEnvelope(
layerSnapshots(dataManager.getAll()).filter((layer) => layer.enabled),
),
};
return getWorldPacket({
viewer,
styleManager,
dataManager,
sceneDirector,
});
}
async function getEntityContext(
@@ -4647,23 +4517,6 @@ function clampNumber(value, min, max, fallback) {
* ("which of those is closest?") scoped to the session.
*/
/**
* The Contacts panel's own counts, or null when Contacts has no subject.
* Read through the awareness snapshot the panel renders, so the two cannot
* diverge no matter which surface asks.
* @returns {object|null} Panel-equivalent window counts.
*/
function activeContactsWindow(dataManager) {
try {
const layer = dataManager?.layers?.get('military-awareness')?.module;
return (
layer?.contactsWindowFromSnapshot?.(layer.getContextSnapshot?.()) ?? null
);
} catch {
return null;
}
}
/**
* Most records one layer hands a single query. Above every loaded feed seen
* so far (flights ~8k, vessels ~12k, a 24 h global FIRMS day ~160k), so