Pass thread name through Add-ons response wrapper so bot replies stay
in the user's thread instead of posting top-level messages. Add
GIT_TERMINAL_PROMPT=0 to Dockerfile to prevent git from hanging on
credential prompts, which was blocking all requests under concurrency=1.
Enable session resumability across Cloud Run restarts:
- executor.ts: Save conversation history in task metadata during
toSDKTask(), restore via setHistory() in reconstruct()
- gcs.ts: Persist conversation history as separate GCS object
(conversation.tar.gz) alongside metadata and workspace
- session-store.ts: Add optional GCS-backed persistence with periodic
flush and restore-on-startup for thread→session mappings
- handler.ts: Restore persisted sessions on initialize()
- types.ts: Add gcsBucket to ChatBridgeConfig
- app.ts: Pass GCS_BUCKET_NAME to chat bridge config
Validated end-to-end: message persists, Cloud Run restarts, follow-up
message in same thread correctly recalls prior context. Different
threads maintain isolation.
Cloud Run strips the Authorization header after using it for IAM
validation, so our JWT middleware can never see the token. When
running on Cloud Run (detected via K_SERVICE env var), skip
app-level JWT verification since Cloud Run IAM already ensures
only authorized service accounts (chat@system.gserviceaccount.com)
can reach the container.
Task history contains multiple status-update messages that may
reference the same A2UI surface. Use only the last non-empty
agent response to avoid duplicate text in Chat output.
The blocking DefaultRequestHandler accumulates intermediate status-update
events into task.history. The A2UI response content from "working" events
lives there, while the final "input-required" status has no message.
Updated extractAllParts to check history. Reverted to blocking mode
since streaming had transport issues.
Verifies Bearer tokens from Google Chat using google-auth-library.
Checks issuer (chat@system.gserviceaccount.com) and audience
(CHAT_PROJECT_NUMBER). Verification is skipped when project number
is not configured, allowing local testing without tokens.
Blocking mode only returns the final task state, missing intermediate
A2UI response content from working status-update events. Streaming
captures all events and aggregates parts into the response.
ClientFactory.createFromUrl expects the full agent card URL
(/.well-known/agent-card.json), not just the base server URL.
Also adds CHAT_BRIDGE_A2A_URL to k8s deployment and test script.
Implements a Google Chat HTTP webhook bridge that connects Google Chat
to the A2A server. Each Chat thread maps to an A2A contextId/taskId
pair. The bridge converts A2UI tool approval surfaces to Google Chat
Cards V2 with Approve/Always Allow/Reject buttons, and handles
CARD_CLICKED events to forward tool confirmations back to the A2A server.
Components:
- chat-bridge/types.ts: Google Chat event/response types
- chat-bridge/session-store.ts: Thread -> A2A session mapping
- chat-bridge/a2a-bridge-client.ts: A2A SDK client wrapper
- chat-bridge/response-renderer.ts: A2UI -> Google Chat Cards V2
- chat-bridge/handler.ts: Event handler (MESSAGE, CARD_CLICKED)
- chat-bridge/routes.ts: Express routes mounted at /chat/webhook