feat(voice): reconcile preview and settings with main

add the shared Voice Preview and Settings panel with browser-local preview
and inactivity preferences, keyboard controls and responsive positioning

preserve main’s Rotation and Context behavior, clarify panel routing and
refresh schema pins within the unchanged prompt limit
This commit is contained in:
manjunath committed 2026-10-24 15:20:15 +05:30
1 parent 9d3548c27c
commit 5c3b66c263
39 files changed
+5274 -111

No files matched your search

+30 -5
View File
@@ -32,7 +32,8 @@ test('the complete Realtime tool payload pins the manifest-generated layer relea
.digest('hex');
assert.equal(
digest,
// Re-derived for the voice layer manifest (generated layer enums and
// Re-derived for Provider Settings and explicit Visual Presets/Scenes routing,
// plus the deliberate direct Panel tool/target additions and voice layer manifest (generated layer enums and
// aliases), point-and-ask (pointer sentinels, referent args) and the
// consolidated tool wording (each policy stated once); model-facing tools
// omit top-level anyOf (OpenAI rejects it). Contacts list routing preserves
@@ -41,8 +42,9 @@ test('the complete Realtime tool payload pins the manifest-generated layer relea
// Air quality (ECCC AQHI) extends the manifest.
// Globe rotation adds one motion; visual keyhole fit and explicit
// reset guidance/defaults update only move_camera and mode descriptions.
// Restore base descriptions; append only globe-rotation defaults and fit guidance.
'967b5a043b812e2f8c1e190fc571cf12b960c9d4486df736902221aab4d99cf6',
// Panel adds named voice targets and timeout; shared Panel/Cockpit guidance
// is consolidated without changing either feature's arguments.
'b2cd2decb77fb3f8f0ab65e7907c221580e21ee3e7e77581f1b52bf62126ae86',
);
});
@@ -100,12 +102,18 @@ test('metadata cannot add tools, fields, types or enum values', () => {
test('all legacy action arguments are byte-identical after removing the deliberate additions', () => {
const legacy = structuredClone(GEV_ACTION_SCHEMAS).filter(
(tool) => !['next_satellite_pass', 'set_cyber_sonar'].includes(tool.name),
(tool) =>
![
'next_satellite_pass',
'set_cyber_sonar',
'set_voice_inactivity_timeout',
].includes(tool.name),
);
// Layer enums are generated from the voice layer manifest and pinned by
// layerManifest.test.mjs; the two shipped right-rail panels are additive.
const property = (name) =>
legacy.find((tool) => tool.name === name).parameters.properties;
delete property('control_cockpit').voicePanel;
delete property('set_layer_visibility').layerId.enum;
delete property('show_data_layers_menu').layerId.enum;
delete property('get_entity_context').layerId.enum;
@@ -123,7 +131,14 @@ test('all legacy action arguments are byte-identical after removing the delibera
motion.enum = motion.enum.filter((value) => value !== 'rotate_globe');
const panels = property('set_panel_open').panelId;
panels.enum = panels.enum.filter(
(id) => !['weather-panel', 'recent-imagery-panel'].includes(id),
(id) =>
![
'weather-panel',
'recent-imagery-panel',
'voice-settings',
'voice-preview',
'provider-settings',
].includes(id),
);
for (const tool of legacy) {
// Point-and-ask adds `referent` arguments and 'pointer' enum values.
@@ -228,3 +243,13 @@ test('globe reset guidance requires a separate explicit command after refusal',
assert.match(paragraph, /bare yes\/ok/);
assert.match(paragraph, /Do not ask a question/);
});
test('direct voice timeout schema accepts None and exact integers, rejects malformed duration', () => {
const tool = GEV_REALTIME_TOOLS.find(
(tool) => tool.name === 'set_voice_inactivity_timeout',
);
for (const minutes of [0, 1, 5, 60])
assert.equal(validateArgs(tool.parameters, { minutes }).length, 0);
for (const minutes of [-1, 61, 1.5, '5'])
assert.ok(validateArgs(tool.parameters, { minutes }).length > 0);
});