mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 10:53:59 +00:00
release: v0.1.0 — one-click install, keyless boot, in-app Provider Settings (#142)
The first formal release. - One-click install via Pinokio; keyless boot lands on a live Esri World Imagery satellite globe with keyless terrain, with automatic OSM fallback and graceful degradation when terrain is unavailable. - Provider Settings (the POWER UP panel): add, replace, or remove API keys inside the app; credential files made owner-only before any secret is written; external keys shown read-only; the panel refuses shared or proxied servers. - Keyless capability responses for the optional HUD summary and place search. - Aircraft-identity voice answers cover operator, type, and route, and say so plainly when enrichment is unavailable. - README rewritten keyless-first; concise 0.1.0 changelog section; CI workflow included. Gates: 2,672 unit tests pass / 0 fail, build clean, tracking regression 108/108, map-source tray QA pass, setup doctor ready.
This commit is contained in:
1 parent
6d83bb6008
commit
b6da93b8ac
170 files changed
+5800
-853
No files matched your search
@@ -91,7 +91,7 @@ const NESTED_CONTEXT_RESULT_FIELDS = Object.freeze(['context', 'contextRollback'
|
||||
* `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 (field session
|
||||
* 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
|
||||
@@ -208,6 +208,10 @@ const STACK_ALIASES = new Map([
|
||||
['bing labels', 'bing-labels'],
|
||||
['labels', 'bing-labels'],
|
||||
['aerial with labels', 'bing-labels'],
|
||||
['esri-imagery', 'esri-imagery'],
|
||||
['esri', 'esri-imagery'],
|
||||
['esri imagery', 'esri-imagery'],
|
||||
['esri satellite', 'esri-imagery'],
|
||||
['osm', 'osm'],
|
||||
['openstreetmap', 'osm'],
|
||||
['open street map', 'osm'],
|
||||
@@ -1038,7 +1042,7 @@ function clearAnnotations(annotations) {
|
||||
return { ok: true, action: 'clear_annotations' };
|
||||
}
|
||||
|
||||
function normalizeStackId(value) {
|
||||
export function normalizeStackId(value) {
|
||||
const raw = String(value || '').trim().toLowerCase();
|
||||
if (!raw) return null;
|
||||
return STACK_ALIASES.get(raw) || null;
|
||||
@@ -3371,7 +3375,7 @@ async function runAnalystQuery(viewer, dataManager, args = {}) {
|
||||
// hand this result straight to track_entity, and `id` is a DISPLAY label
|
||||
// (callsign, else registration, else hex). A callsign-less contact therefore
|
||||
// handed track_entity a tail number the lookup could not resolve, and the
|
||||
// model burned the turn on retries (field session 2026-08-21, 23:48).
|
||||
// model burned the turn on retries (owner field session 2026-08-21, 23:48).
|
||||
const items = result.items.map((r) => {
|
||||
const compact = { layerKey: r.layerKey, id: r.id };
|
||||
for (const k of ['icao24', 'mmsi', 'registration', 'label', 'callsign', 'name', 'altitudeM', 'speedMps', 'speedKts', 'frp', 'magnitude', 'shipType', 'destination', 'operator', 'routeOrigin', 'routeDestination', 'aircraftClass', 'military', 'onGround', 'distanceKm', 'confidence', 'place']) {
|
||||
@@ -3413,7 +3417,7 @@ async function runAnalystQuery(viewer, dataManager, args = {}) {
|
||||
const aircraftQueried = (result.coverage?.layersQueried || [])
|
||||
.some((l) => l.layerKey === 'flights' || l.layerKey === 'military');
|
||||
// Both numbers, and which one answers the question. The window counts have
|
||||
// ridden along in `contactsWindow` for a while, and the live trial showed
|
||||
// ridden along in `contactsWindow` for a while, and the owner's trial showed
|
||||
// that is not enough on its own: with Contacts active and a DATACENTER in
|
||||
// the selection slot, the model centred a radius on the datacenter, answered
|
||||
// 15, and then explained away the 111 sitting in the same payload ("that
|
||||
|
||||
@@ -14,7 +14,37 @@ import {
|
||||
cctvVoiceFocusOutcome,
|
||||
formatTrackedEntityLabel,
|
||||
knownRadioLocation,
|
||||
normalizeStackId,
|
||||
} from './gevActions.js';
|
||||
import { MAP_STACKS } from '../mapStackController.js';
|
||||
import { readFileSync } from 'node:fs';
|
||||
|
||||
test('every live basemap is reachable by its own id — no enum value without a voice alias', () => {
|
||||
// B1 regression: a stack added to MAP_STACKS (and the set_map_stack enum)
|
||||
// without a matching STACK_ALIASES entry resolves to null and throws
|
||||
// "Unknown map stack" at the controller — a broken voice command for a
|
||||
// shipped basemap. Every live id must self-resolve.
|
||||
for (const stack of MAP_STACKS) {
|
||||
assert.equal(
|
||||
normalizeStackId(stack.id),
|
||||
stack.id,
|
||||
`set_map_stack '${stack.id}' has no self-mapping alias — voice selection would throw`,
|
||||
);
|
||||
}
|
||||
// The Esri phrasings the voice prompt promises must also resolve.
|
||||
assert.equal(normalizeStackId('Esri'), 'esri-imagery');
|
||||
assert.equal(normalizeStackId('esri imagery'), 'esri-imagery');
|
||||
// And the voice tool's enum must equal the set of live ids — no drift either way.
|
||||
const config = readFileSync(new URL('../../vite.config.js', import.meta.url), 'utf8');
|
||||
const enumMatch = config.match(/enum: \[('photoreal'[^\]]*)\],\s*\n\s*description: 'photoreal = Google 3D/);
|
||||
assert.ok(enumMatch, 'set_map_stack enum literal must still be findable');
|
||||
const enumIds = enumMatch[1].split(',').map((s) => s.trim().replace(/^'|'$/g, ''));
|
||||
assert.deepEqual(
|
||||
[...enumIds].sort(),
|
||||
MAP_STACKS.map((s) => s.id).sort(),
|
||||
'the set_map_stack voice enum and MAP_STACKS must name exactly the same basemaps',
|
||||
);
|
||||
});
|
||||
|
||||
test('track_entity narration names aircraft callsign → registration → icao24', () => {
|
||||
const found = { callsign: 'SWA696', registration: 'N123AB', icao24: 'ae1fa4' };
|
||||
@@ -2774,7 +2804,7 @@ test('a nested Cockpit rollback result is translated too', async () => {
|
||||
|
||||
|
||||
/**
|
||||
* Front 5 (the live trial, 2026-08-22 01:42-01:44). Contacts was active
|
||||
* Front 5 (owner's live trial, 2026-08-22 01:42-01:44). Contacts was active
|
||||
* with contact N546PC as its subject, a DATACENTER sat in the recency slot,
|
||||
* and "how many nearby" produced 15 from a radius centred on the datacenter
|
||||
* while the panel showed 111. Two causes: the wrong centre, and two different
|
||||
|
||||
Reference in new issue
Block a user