claude-flow
Version:
Ruflo - Enterprise AI agent orchestration for Claude Code. Deploy 60+ specialized agents in coordinated swarms with self-learning, fault-tolerant consensus, vector memory, and MCP integration
126 lines • 4.63 kB
TypeScript
/**
* GAIA Tool: grounded_query — ADR-135 / iter-33
*
* Calls Gemini 2.5 Flash with the google_search grounding tool and returns
* a synthesised factual answer plus source citations in a single API call.
*
* Architectural advantage over web_search (Google Custom Search):
* - web_search: raw snippets → agent reads + parses → 2-3 extra turns
* - grounded_query: Gemini synthesises an answer + cites sources in 1 call
*
* This is Ruflo's cross-provider stack in action:
* Gemini grounds (google_search tool) → Sonnet/Haiku reasons → answer
*
* Credential resolution (mirrors performance-capability.ts / web_search.ts):
* 1. process.env.GOOGLE_AI_API_KEY
* 2. gcloud secrets versions access latest --secret=GOOGLE_AI_API_KEY --project=ruv-dev
* 3. Throws with clear instructions if neither is available
*
* Free tier: 1500 grounded queries/day on Gemini 2.5 Flash.
* Pricing: ~$0.075/M input tokens, ~$0.30/M output tokens, grounding free <1500/day.
*
* Regression note (iter-47): this file was absent from feat/adr-135-integrate-tracks
* because the grounded-query-gemini branch was not cherry-picked during Track integration.
* The omission caused a 36-question empty-answer failure in iter-42 (13.2% vs 49.1% baseline).
*
* Refs: ADR-133, ADR-135, iter-30 research, iter-33, iter-47, #2156
* Live-tested 2026-05-27: Mercedes Sosa GAIA L1 question → HTTP 200, 4 sources.
*/
import { GaiaTool, ToolDefinition } from './types.js';
export interface GroundedQueryInput {
query: string;
max_tokens?: number;
}
export interface GroundedQuerySource {
title: string;
uri: string;
snippet?: string;
}
export interface GroundedQueryResult {
/** Synthesised factual answer from Gemini. */
answer: string;
/** Web pages Gemini cited when composing its answer. */
sources: GroundedQuerySource[];
/** Auto-formulated search queries issued by Gemini. */
search_queries_used: string[];
/** True when grounding metadata was returned (sources or search_queries present). */
grounded: boolean;
/** Always 'gemini-2.5-flash' for this tool. */
model: string;
/** Estimated cost in USD. */
cost_usd: number;
}
interface GeminiPart {
text?: string;
}
interface GeminiGroundingChunk {
web?: {
title?: string;
uri?: string;
};
}
interface GeminiGroundingSupport {
groundingChunkIndices?: number[];
segment?: {
text?: string;
};
}
interface GeminiGroundingMetadata {
groundingChunks?: GeminiGroundingChunk[];
webSearchQueries?: string[];
groundingSupports?: GeminiGroundingSupport[];
}
interface GeminiCandidate {
content?: {
parts?: GeminiPart[];
};
groundingMetadata?: GeminiGroundingMetadata;
}
interface GeminiUsageMetadata {
promptTokenCount?: number;
candidatesTokenCount?: number;
}
interface GeminiGenerateContentResponse {
candidates?: GeminiCandidate[];
usageMetadata?: GeminiUsageMetadata;
}
export interface GroundedQueryTestHooks {
/** Override the API key resolver. */
resolveKey?: () => Promise<string>;
/** Override the actual HTTP fetch so tests never make live calls. */
fetchResponse?: (query: string, maxTokens: number, apiKey: string) => Promise<GeminiGenerateContentResponse>;
}
export declare const groundedQueryTestHooks: GroundedQueryTestHooks;
/**
* Resolve a Google AI API key.
*
* Order: env var → gcloud secret → throw.
* Never returns null — throws with actionable guidance if no key is found.
*/
export declare function resolveGoogleAIApiKey(): Promise<string>;
/**
* Call Gemini 2.5 Flash with google_search grounding and parse the response.
*
* Exported so smoke tests can exercise the parser without live HTTP (via
* groundedQueryTestHooks.fetchResponse).
*/
export declare function callGeminiGrounded(query: string, maxTokens: number, apiKey: string): Promise<GroundedQueryResult>;
/**
* Parse a raw Gemini generateContent response into GroundedQueryResult.
* Exported for unit testing the parser independently.
*/
export declare function parseGeminiResponse(body: GeminiGenerateContentResponse): GroundedQueryResult;
export declare class GroundedQueryTool implements GaiaTool {
readonly name = "grounded_query";
readonly definition: ToolDefinition;
private readonly apiKey?;
constructor(opts?: {
apiKey?: string;
});
execute(input: Record<string, unknown>): Promise<string>;
}
export declare function createGroundedQueryTool(opts?: {
apiKey?: string;
}): GroundedQueryTool;
export {};
//# sourceMappingURL=grounded_query.d.ts.map