mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-05-22 17:53:04 -07:00
fix: Cloud Run service-to-service auth and agent card URL
- Add identity token auth in A2ABridgeClient for Cloud Run (K_SERVICE) - Support CODER_AGENT_PUBLIC_URL env var for agent card URL on Cloud Run - Strip @Bot mention prefix before slash command detection (Add-ons) - Grant bridge SA roles/run.invoker on A2A server via IAM
This commit is contained in:
@@ -27,6 +27,7 @@ import {
|
||||
RestTransportFactory,
|
||||
JsonRpcTransportFactory,
|
||||
} from '@a2a-js/sdk/client';
|
||||
import { GoogleAuth } from 'google-auth-library';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { logger } from '../utils/logger.js';
|
||||
|
||||
@@ -162,17 +163,37 @@ export class A2ABridgeClient {
|
||||
|
||||
/**
|
||||
* Initializes the client connection to the A2A server.
|
||||
* On Cloud Run (K_SERVICE is set), wraps fetch with an identity token
|
||||
* for service-to-service authentication.
|
||||
*/
|
||||
async initialize(): Promise<void> {
|
||||
if (this.client) return;
|
||||
|
||||
const resolver = new DefaultAgentCardResolver({});
|
||||
// On Cloud Run, create an authenticated fetch that adds identity tokens
|
||||
let fetchImpl: typeof fetch = fetch;
|
||||
if (process.env['K_SERVICE']) {
|
||||
const auth = new GoogleAuth();
|
||||
const idTokenClient = await auth.getIdTokenClient(this.agentUrl);
|
||||
fetchImpl = async (input, init?) => {
|
||||
const authHeaders = await idTokenClient.getRequestHeaders();
|
||||
const merged = new Headers(init?.headers);
|
||||
for (const [key, value] of Object.entries(authHeaders)) {
|
||||
merged.set(key, value);
|
||||
}
|
||||
return fetch(input, { ...init, headers: merged });
|
||||
};
|
||||
logger.info(
|
||||
'[ChatBridge] Using Cloud Run identity token for A2A server auth',
|
||||
);
|
||||
}
|
||||
|
||||
const resolver = new DefaultAgentCardResolver({ fetchImpl });
|
||||
const options = ClientFactoryOptions.createFrom(
|
||||
ClientFactoryOptions.default,
|
||||
{
|
||||
transports: [
|
||||
new RestTransportFactory({}),
|
||||
new JsonRpcTransportFactory({}),
|
||||
new RestTransportFactory({ fetchImpl }),
|
||||
new JsonRpcTransportFactory({ fetchImpl }),
|
||||
],
|
||||
cardResolver: resolver,
|
||||
},
|
||||
|
||||
@@ -100,7 +100,10 @@ export class ChatBridgeHandler {
|
||||
return { text: 'Error: Missing thread information.' };
|
||||
}
|
||||
|
||||
const text = message.argumentText || message.text || '';
|
||||
// argumentText has bot mentions stripped (legacy format only).
|
||||
// For Add-ons format, strip leading @mention manually.
|
||||
const rawText = message.argumentText || message.text || '';
|
||||
const text = rawText.replace(/^@\S+\s*/, '');
|
||||
if (!text.trim()) {
|
||||
return { text: "I didn't receive any text. Please try again." };
|
||||
}
|
||||
|
||||
@@ -77,7 +77,11 @@ const coderAgentCard: AgentCard = {
|
||||
};
|
||||
|
||||
export function updateCoderAgentCardUrl(port: number) {
|
||||
coderAgentCard.url = `http://localhost:${port}/`;
|
||||
// On Cloud Run, use the public service URL so remote clients can reach us
|
||||
const publicUrl = process.env['CODER_AGENT_PUBLIC_URL'];
|
||||
coderAgentCard.url = publicUrl
|
||||
? publicUrl.replace(/\/$/, '') + '/'
|
||||
: `http://localhost:${port}/`;
|
||||
}
|
||||
|
||||
async function handleExecuteCommand(
|
||||
|
||||
Reference in New Issue
Block a user