fix(voice): offer typed chat the same Overpass tools as voice

Main now offers osm_query, and names it in the prompt, only when Overpass
is configured. Typed chat follows the same switch on both providers: its
prompt, the tools it offers and the calls it accepts.
This commit is contained in:
manjunath22466 committed 2026-11-04 00:17:54 +05:30
1 parent fe78b3ebc9
commit 39165bb199
4 files changed
+59 -13

No files matched your search

+3 -2
View File
@@ -15,8 +15,9 @@ export const TEXT_WORDING = Object.freeze([
// Shared-manual adaptation follows Darren Dignam's GEV COMMAND approach (#976).
// Keep our Radio handoff and annotation outcome policies from the shared manual.
export function textInstructions(annotationGuidance) {
return realtimeDirectives(annotationGuidance)
// `options.overpass` matches the tools offered, as for voice.
export function textInstructions(annotationGuidance, options) {
return realtimeDirectives(annotationGuidance, options)
.map((line, index) => {
if (index === 0)
return "You are GEV Chat, a concise text assistant for a Cesium geospatial app called God's Eye View.";
+14 -4
View File
@@ -1,7 +1,8 @@
import { createTextChatHandler } from '../common/textChat.js';
import { invalidCalls } from '../common/textTools.js';
import { textInstructions } from '../common/textInstructions.js';
import { GEV_REALTIME_TOOLS } from '../openai/tools.js';
import { GEV_REALTIME_TOOLS, offeredTools } from '../openai/tools.js';
import { resolveOverpassUpstreams } from '../overpass/constants.js';
import { normalizeGeminiModel } from './config.js';
// The Gemini token route's throttle default (GEV_RATELIMIT_GEMINI_PER_MIN).
@@ -80,6 +81,9 @@ export function validChatContents(contents, names) {
export function createGeminiChatHandler({
annotationGuidance,
tools = GEV_REALTIME_TOOLS,
// osm_query is offered, and the prompt names it, only with Overpass, as
// for voice.
overpassConfigured = () => resolveOverpassUpstreams().length > 0,
resolveChatModel = () =>
process.env.GEMINI_CHAT_MODEL || 'gemini-3.5-flash-lite',
resolveApiKey = () => process.env.GEMINI_API_KEY,
@@ -102,17 +106,20 @@ export function createGeminiChatHandler({
)
return null;
if (!pairedContents(input.contents)) return null;
const overpass = overpassConfigured();
return {
endpoint: `https://generativelanguage.googleapis.com/v1beta/models/${model}:generateContent`,
headers: (key) => ({ 'x-goog-api-key': key }),
body: {
contents: input.contents,
systemInstruction: {
parts: [{ text: textInstructions(annotationGuidance) }],
parts: [
{ text: textInstructions(annotationGuidance, { overpass }) },
],
},
tools: [
{
functionDeclarations: tools.map(
functionDeclarations: offeredTools(tools, { overpass }).map(
({ name, description, parameters }) => ({
name,
description,
@@ -144,7 +151,10 @@ export function createGeminiChatHandler({
return {
content,
finishReason: candidate.finishReason,
invalidCalls: invalidCalls(calls, tools),
invalidCalls: invalidCalls(
calls,
offeredTools(tools, { overpass: overpassConfigured() }),
),
};
},
});
+20 -7
View File
@@ -3,7 +3,8 @@ import { preferCodexOAuth } from './codex-auth.js';
import { OPENAI_DEFAULT_PER_MIN } from './rate-limit.js';
import { invalidCalls } from '../common/textTools.js';
import { textInstructions } from '../common/textInstructions.js';
import { GEV_REALTIME_TOOLS } from './tools.js';
import { GEV_REALTIME_TOOLS, offeredTools } from './tools.js';
import { resolveOverpassUpstreams } from '../overpass/constants.js';
const object = (value) =>
value && typeof value === 'object' && !Array.isArray(value);
@@ -66,6 +67,9 @@ function validMessages(messages) {
export function createOpenAiChatHandler({
annotationGuidance,
tools = GEV_REALTIME_TOOLS,
// osm_query is offered, and the prompt names it, only with Overpass, as
// for voice.
overpassConfigured = () => resolveOverpassUpstreams().length > 0,
resolveApiKey = () => process.env.OPENAI_API_KEY,
resolveChatModel = () => process.env.OPENAI_CHAT_MODEL || 'gpt-4.1-mini',
resolveProviderRateLimit = () => process.env.GEV_RATELIMIT_OPENAI_PER_MIN,
@@ -102,6 +106,7 @@ export function createOpenAiChatHandler({
!validMessages(input.messages)
)
return null;
const overpass = overpassConfigured();
return {
endpoint: 'https://api.openai.com/v1/chat/completions',
headers: (key) => ({ Authorization: `Bearer ${key}` }),
@@ -112,13 +117,18 @@ export function createOpenAiChatHandler({
store: false,
max_completion_tokens: 4096,
messages: [
{ role: 'system', content: textInstructions(annotationGuidance) },
{
role: 'system',
content: textInstructions(annotationGuidance, { overpass }),
},
...input.messages,
],
tools: tools.map(({ name, description, parameters }) => ({
type: 'function',
function: { name, description, parameters, strict: false },
})),
tools: offeredTools(tools, { overpass }).map(
({ name, description, parameters }) => ({
type: 'function',
function: { name, description, parameters, strict: false },
}),
),
},
};
},
@@ -149,7 +159,10 @@ export function createOpenAiChatHandler({
return {
content,
finishReason: choice.finish_reason,
invalidCalls: invalidCalls(calls, tools),
invalidCalls: invalidCalls(
calls,
offeredTools(tools, { overpass: overpassConfigured() }),
),
};
},
});