Streaming fixes:
- Fix A2UI text extraction preferring incremental chunks over accumulated
text by swapping push order in extractFromStreamEvent
- Defer tool approval handling to post-stream — server YOLO mode briefly
publishes awaiting_approval before auto-approving, which was breaking
the stream loop prematurely
- Always update latestPendingApprovals to clear stale approvals after
server auto-approves
Message chunking:
- Split long messages at paragraph/line boundaries to stay within Google
Chat's 4096 character limit
- Cards attach to first chunk only
Streaming tool confirmations:
- Add sendToolConfirmationStream and sendBatchToolConfirmationsStream
for SSE-based tool approval flow
README:
- Update bridge deployment to max-instances=1 (single instance for
in-memory async guard consistency)
- Add Known Limitations section
Working:
- Server YOLO mode with streaming text extraction
- Chat API push with proper threading
- Session persistence across Cloud Run restarts
- Retry logic for agent concurrency exhaustion
- Text chunking for long responses
- Per-session /yolo and /safe commands
Not working:
- Tool confirmation streaming with GEMINI_YOLO_MODE=false (executor
aborts on SSE disconnect — SDK-level issue)
- CARD_CLICKED button routing through Add-ons (text-based approval
works as fallback)
Separate the Google Chat bridge from the A2A agent server so each can
scale independently on Cloud Run. The bridge is a lightweight proxy
(concurrency=80) while the agent needs concurrency=1.
- Add standalone entry point (src/chat-bridge/server.ts)
- Add Dockerfile.chat-bridge and cloudbuild-chat-bridge.yaml
- Remove chat bridge setup from app.ts
- Inline A2UI constants in a2a-bridge-client.ts (no agent deps)
- Update README for two-service architecture
Replace blocking A2A calls with streaming: webhook returns
immediate "Processing..." response, then streams results from
A2A agent and pushes them to Google Chat via REST API.
- Add ChatApiClient for proactive messaging via Chat REST API
- Add sendMessageStream() to A2ABridgeClient for SSE streaming
- Add extractFromStreamEvent() for parsing individual stream events
- Refactor handler to fire-and-forget async processing
- Fix isTerminal logic to use stream state instead of taskId presence
- Add asyncProcessing guard to prevent overlapping requests
- Add comprehensive README with deployment and setup guide