mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 10:53:59 +00:00
Merge remote-tracking branch 'upstream/main' into fix/363-geocode-proxy
# Conflicts: # SECURITY.md # server/providers/places/google.js
This commit is contained in:
commit
e2ce7fa38e
223 files changed
+20759
-1752
No files matched your search
@@ -688,7 +688,7 @@ export function createGevActionRunner({
|
||||
const style = normalizeStyle(args.style);
|
||||
if (!style)
|
||||
throw new Error(`Unknown visual style: ${args.style || 'missing'}`);
|
||||
styleManager.setStyle(style);
|
||||
styleManager.setStyle(style, { userInitiated: true });
|
||||
return { ok: true, action: 'set_visual_style', style };
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,35 @@
|
||||
import { toFunctionOutput } from '../tools/functions.js';
|
||||
import { GEV_ACTION_SCHEMAS } from './actionSchemas.js';
|
||||
import { createGevActionRunner } from './gevActions.js';
|
||||
import { createVoiceCommands } from './commands.js';
|
||||
export * from './realtimeController.js';
|
||||
|
||||
const ACTION_NAMES = new Set(GEV_ACTION_SCHEMAS.map((schema) => schema.name));
|
||||
|
||||
/**
|
||||
* Run app actions through `runner` and every other tool the catalog has
|
||||
* through the catalog. `loadCatalog` resolves the catalog when first needed.
|
||||
*/
|
||||
export function withToolCatalog(runner, loadCatalog) {
|
||||
if (typeof loadCatalog !== 'function') return runner;
|
||||
return async function runGevTool(name, args, options = {}) {
|
||||
if (ACTION_NAMES.has(name)) return runner(name, args, options);
|
||||
const catalog = await loadCatalog();
|
||||
if (!catalog?.get(name)) return runner(name, args, options);
|
||||
const result = await catalog.call(name, args ?? {}, {
|
||||
signal: options.signal,
|
||||
});
|
||||
return toFunctionOutput(name, result);
|
||||
};
|
||||
}
|
||||
|
||||
/** Compose the standalone action runner with the voice controls. */
|
||||
export function initGevVoiceCommands(options) {
|
||||
return createVoiceCommands({
|
||||
...options,
|
||||
runner: createGevActionRunner(options),
|
||||
runner: withToolCatalog(
|
||||
createGevActionRunner(options),
|
||||
options.toolCatalog,
|
||||
),
|
||||
});
|
||||
}
|
||||
@@ -31,6 +31,7 @@ import {
|
||||
readStoredVoiceLimits,
|
||||
writeStoredVoiceTier,
|
||||
writeStoredVoiceLimits,
|
||||
withToolCatalog,
|
||||
} from './gevRealtime.js';
|
||||
import { createVoiceCostTracker } from './voiceCost.js';
|
||||
|
||||
@@ -3681,3 +3682,43 @@ test('a genuinely different refused call still gets its own output', async () =>
|
||||
const testPlaceSearch = () => createStandalonePlaceSearch({ resolveApiKey: () => globalThis.window?.__GOOGLE_MAPS_API_KEY__ });
|
||||
function createGevActionRunner(options) { return createActionRunner({ placeSearch: testPlaceSearch(), ...options }); }
|
||||
function controlRadio(viewer, manager, args, options) { return runControlRadio(viewer, manager, args, { placeSearch: testPlaceSearch(), ...options }); }
|
||||
|
||||
test('voice runs app actions itself and other tools through the catalog', async () => {
|
||||
const actions = [];
|
||||
const runner = async (name, args) => {
|
||||
actions.push([name, args]);
|
||||
return { ok: true, action: name };
|
||||
};
|
||||
const calls = [];
|
||||
let loads = 0;
|
||||
const catalog = {
|
||||
get: (name) => (name === 'get_wind' ? { name } : undefined),
|
||||
async call(name, args, options) {
|
||||
calls.push([name, args, options.signal]);
|
||||
return { summary: 'Calm.', data: { calm: true } };
|
||||
},
|
||||
};
|
||||
const run = withToolCatalog(runner, async () => {
|
||||
loads += 1;
|
||||
return catalog;
|
||||
});
|
||||
const signal = new AbortController().signal;
|
||||
assert.deepEqual(await run('zoom_to_globe', {}), {
|
||||
ok: true,
|
||||
action: 'zoom_to_globe',
|
||||
});
|
||||
assert.equal(loads, 0);
|
||||
assert.deepEqual(
|
||||
await run('get_wind', { location: { place: 'Oslo' } }, { signal }),
|
||||
{ ok: true, tool: 'get_wind', summary: 'Calm.', data: { calm: true } },
|
||||
);
|
||||
assert.deepEqual(calls, [
|
||||
['get_wind', { location: { place: 'Oslo' } }, signal],
|
||||
]);
|
||||
await run('not_a_tool', {});
|
||||
assert.deepEqual(
|
||||
actions.map(([name]) => name),
|
||||
['zoom_to_globe', 'not_a_tool'],
|
||||
);
|
||||
assert.equal(withToolCatalog(runner, undefined), runner);
|
||||
});
|
||||
Reference in new issue
Block a user