mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 19:04:02 +00:00
Merge feat/voice-geometry onto main
Both stack parents (#837, #842) are on main, so the voice geometry branch now builds on main directly. Conflict resolutions keep main's behaviour and add the geometry work on top: osm_query gating on every provider, restored admin identity for Nominatim outlines, merged analyst follow-up memory, and the cancelled Globe View reset instruction ahead of the generic cancellation.
This commit is contained in:
commit
ecaddd838b
102 files changed
+12925
-1006
No files matched your search
@@ -20,7 +20,11 @@ import {
|
||||
import { openAiRealtimeProxy } from 'gods-eye-view/server/providers/openai';
|
||||
import { keySetupEndpoint } from 'gods-eye-view/server/standalone/key-setup';
|
||||
import { realtimeInstructions } from '../../server/providers/openai/instructions.js';
|
||||
import { GEV_REALTIME_TOOLS } from '../../server/providers/openai/tools.js';
|
||||
import {
|
||||
GEV_REALTIME_TOOLS,
|
||||
offeredTools,
|
||||
realtimeTools,
|
||||
} from '../../server/providers/openai/tools.js';
|
||||
import { createDebugLogHandler } from '../../server/providers/openai/debug-log.js';
|
||||
import { attachVoiceResult } from '../voice/speech.js';
|
||||
import { sanitizeDebugValue } from '../voice/realtimeDiagnostics.js';
|
||||
@@ -164,6 +168,7 @@ test('weather-only requests share upstream work and retain fresh and stale respo
|
||||
test('Realtime handler preserves tools and default instructions, isolates supplied annotation guidance, and keeps the upstream key server-side', async (t) => {
|
||||
env(t, 'OPENAI_API_KEY', 'fixture-upstream-secret');
|
||||
env(t, 'GEV_RATELIMIT_OPENAI_PER_MIN', undefined);
|
||||
env(t, 'OVERPASS_UPSTREAMS', undefined);
|
||||
const sent = [];
|
||||
t.mock.method(globalThis, 'fetch', async (url, options) => {
|
||||
assert.equal(url, 'https://api.openai.com/v1/realtime/client_secrets');
|
||||
@@ -194,7 +199,7 @@ test('Realtime handler preserves tools and default instructions, isolates suppli
|
||||
sent.at(-1).session.instructions,
|
||||
realtimeInstructions(guidance),
|
||||
);
|
||||
assert.deepEqual(sent.at(-1).session.tools, GEV_REALTIME_TOOLS);
|
||||
assert.deepEqual(sent.at(-1).session.tools, realtimeTools());
|
||||
}
|
||||
assert.notEqual(sent[0].session.instructions, sent[1].session.instructions);
|
||||
assert.equal(sent[0].session.instructions, sent[2].session.instructions);
|
||||
@@ -580,6 +585,36 @@ test('OAuth login endpoint selects an existing local sign-in without launching C
|
||||
assert.equal(response.body.includes('fixture-existing-secret'), false);
|
||||
});
|
||||
|
||||
test('osm_query is offered only when an operator configured Overpass', async (t) => {
|
||||
env(t, 'OPENAI_API_KEY', 'fixture-upstream-secret');
|
||||
env(t, 'GEV_RATELIMIT_OPENAI_PER_MIN', undefined);
|
||||
const sent = [];
|
||||
t.mock.method(globalThis, 'fetch', async (_url, options) => {
|
||||
sent.push(JSON.parse(options.body).session);
|
||||
return Response.json({ value: 'fixture-ephemeral' });
|
||||
});
|
||||
const mint = () =>
|
||||
request(install(openAiRealtimeProxy({})).get('/api/realtime/token'), {
|
||||
url: '/',
|
||||
});
|
||||
env(t, 'OVERPASS_UPSTREAMS', undefined);
|
||||
await mint();
|
||||
env(t, 'OVERPASS_UPSTREAMS', 'https://overpass.example/api/interpreter');
|
||||
await mint();
|
||||
const [plain, configured] = sent;
|
||||
const names = (session) => session.tools.map((tool) => tool.name);
|
||||
assert.equal(names(plain).includes('osm_query'), false);
|
||||
assert.doesNotMatch(plain.instructions, /osm_query/);
|
||||
assert.ok(names(plain).includes('resolve_area'));
|
||||
assert.ok(names(plain).includes('find_imagery'));
|
||||
assert.deepEqual(configured.tools, GEV_REALTIME_TOOLS);
|
||||
assert.match(configured.instructions, /osm_query/);
|
||||
assert.equal(
|
||||
configured.instructions,
|
||||
realtimeInstructions(undefined, { overpass: true }),
|
||||
);
|
||||
});
|
||||
|
||||
test('caption transcription is on by default, reported to the client meter, and can be turned off', async (t) => {
|
||||
env(t, 'OPENAI_API_KEY', 'fixture-upstream-secret');
|
||||
env(t, 'GEV_RATELIMIT_OPENAI_PER_MIN', undefined);
|
||||
@@ -607,6 +642,7 @@ test('caption transcription is on by default, reported to the client meter, and
|
||||
test('Realtime sessions carry supplied tools, and the standalone voice adds the catalog queries', async (t) => {
|
||||
env(t, 'OPENAI_API_KEY', 'fixture-upstream-secret');
|
||||
env(t, 'GEV_RATELIMIT_OPENAI_PER_MIN', undefined);
|
||||
env(t, 'OVERPASS_UPSTREAMS', undefined);
|
||||
const sent = [];
|
||||
t.mock.method(globalThis, 'fetch', async (url, options) => {
|
||||
sent.push(JSON.parse(options.body));
|
||||
@@ -619,7 +655,11 @@ test('Realtime sessions carry supplied tools, and the standalone voice adds the
|
||||
),
|
||||
);
|
||||
assert.equal(response.status, 200);
|
||||
assert.deepEqual(sent.at(-1).session.tools, tools);
|
||||
// Without an operator Overpass, osm_query is left out of the session.
|
||||
assert.deepEqual(sent.at(-1).session.tools, offeredTools(tools));
|
||||
assert.ok(
|
||||
!sent.at(-1).session.tools.some(({ name }) => name === 'osm_query'),
|
||||
);
|
||||
const names = tools.map((tool) => tool.name);
|
||||
assert.equal(new Set(names).size, names.length);
|
||||
assert.deepEqual(
|
||||
@@ -713,7 +753,12 @@ test('Realtime service configuration selects compatible endpoint/model without f
|
||||
assert.equal(options.headers.Authorization, 'Bearer server-fixture');
|
||||
const payload = JSON.parse(options.body);
|
||||
assert.equal(payload.session.model, 'configured-model');
|
||||
assert.deepEqual(payload.session.tools, GEV_REALTIME_TOOLS);
|
||||
assert.deepEqual(
|
||||
payload.session.tools.map((tool) => tool.name),
|
||||
realtimeTools({
|
||||
overpass: Boolean(process.env.OVERPASS_UPSTREAMS),
|
||||
}).map((tool) => tool.name),
|
||||
);
|
||||
return Response.json({ value: 'short-lived-fixture' });
|
||||
},
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user