everything-gemini 2.1.0 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/BENCHMARK.md +106 -0
- package/CHANGELOG.md +81 -0
- package/PARTNERSHIP.md +100 -0
- package/README.md +63 -6
- package/ROADMAP_AGI_v3.0.md +109 -0
- package/agents/resilience-engineer.md +36 -0
- package/agents/swarm-coordinator.md +35 -0
- package/bin/everything-gemini +950 -12
- package/docs/LAUNCH_KIT_v2.2.0.md +168 -0
- package/docs/LAUNCH_KIT_v2.4.0.md +164 -0
- package/docs/LAUNCH_KIT_v2.5.0.md +187 -0
- package/docs/index.html +20 -10
- package/examples/python-sdk/ephemeral_swarm_orchestration.py +169 -0
- package/examples/python-sdk/resilience_and_telemetry_pipeline.py +183 -0
- package/hooks/drift-detector/hooks.json +16 -0
- package/hooks/drift-detector/scripts/detect-drift.sh +50 -0
- package/hooks/human-gate/hooks.json +16 -0
- package/hooks/human-gate/scripts/human-gate.sh +67 -0
- package/hooks/thinking-budget/hooks.json +16 -0
- package/hooks/thinking-budget/scripts/budget-thinking.sh +56 -0
- package/package.json +1 -1
- package/skills/bigquery-vector-search/SKILL.md +205 -0
- package/skills/cloud-run-agents/SKILL.md +167 -0
- package/skills/context-warmer/SKILL.md +140 -0
- package/skills/cost-oracle-finops/SKILL.md +142 -0
- package/skills/dynamic-thinking-allocation/SKILL.md +105 -0
- package/skills/ebpf-sandbox-enforcer/SKILL.md +101 -0
- package/skills/envoy-ai-gateway/SKILL.md +175 -0
- package/skills/ephemeral-swarm-orchestrator/SKILL.md +124 -0
- package/skills/gemini-live-multimodal/SKILL.md +149 -0
- package/skills/harness3-mutation-testing/SKILL.md +120 -0
- package/skills/opentelemetry-agent-observability/SKILL.md +139 -0
- package/skills/pubsub-event-mesh/SKILL.md +179 -0
- package/skills/quantum-safe-cryptography/SKILL.md +84 -0
- package/skills/spanner-change-streams/SKILL.md +88 -0
- package/skills/spanner-graph-rag/SKILL.md +167 -0
- package/skills/vertex-ai-feature-store/SKILL.md +110 -0
- package/skills/webrtc-agent-gateway/SKILL.md +199 -0
- package/tests/cli.test.js +189 -14
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: spanner-graph-rag
|
|
3
|
+
description: Implements Google Cloud Spanner Graph schemas, ISO GQL queries, knowledge graph traversal, and hybrid graph-vector RAG pipelines for Gemini agents.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Spanner Graph & Knowledge Graph RAG
|
|
7
|
+
|
|
8
|
+
Designs, provisions, and queries distributed enterprise knowledge graphs using Google Cloud Spanner Graph. Implements ISO GQL (Graph Query Language) multi-hop traversals, cyclic graph pattern matching, and hybrid Graph-Vector RAG to eliminate hallucinations across complex organizational entity networks.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## 1. Architecture: Graph-Grounded Agentic Reasoning
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
Google Cloud Spanner
|
|
16
|
+
┌─────────────────────────────────────────────────────────────────────────────┐
|
|
17
|
+
│ SPANNER DISTRIBUTED GRAPH ENGINE │
|
|
18
|
+
│ │
|
|
19
|
+
│ ┌─────────────────────┐ ┌───────────────────────────┐ │
|
|
20
|
+
│ │ Node Table: Account │ │ Node Table: Microservice │ │
|
|
21
|
+
│ │ (Enterprise Org) │ │ (Infrastructure Artifact) │ │
|
|
22
|
+
│ └──────────┬──────────┘ └─────────────┬─────────────┘ │
|
|
23
|
+
│ │ │ │
|
|
24
|
+
│ │ Edge: OWNS Edge: CALLS │ │
|
|
25
|
+
│ └────────────────► [TEAM] ───────────────────┘ │
|
|
26
|
+
│ │ │
|
|
27
|
+
│ ▼ │
|
|
28
|
+
│ ┌─────────────────────────────┐ │
|
|
29
|
+
│ │ Edge: MUTATES_RESOURCE │ │
|
|
30
|
+
│ │ Destination: Cloud Database │ │
|
|
31
|
+
│ └──────────────┬──────────────┘ │
|
|
32
|
+
│ │ │
|
|
33
|
+
│ ▼ │
|
|
34
|
+
│ ┌───────────────────────────────────────────────┐ │
|
|
35
|
+
│ │ ISO GQL Multi-Hop Graph Traversal │ │
|
|
36
|
+
│ │ MATCH (t:Team)-[:CALLS*1..3]->(m:Service) │ │
|
|
37
|
+
│ └──────────────────────┬────────────────────────┘ │
|
|
38
|
+
│ │ Grounded Entity Context │
|
|
39
|
+
│ ▼ │
|
|
40
|
+
│ ┌───────────────────────────────────────────────┐ │
|
|
41
|
+
│ │ Gemini 2.0 / 3.8 Reasoning & Action Engine │ │
|
|
42
|
+
│ │ Zero hallucination on architectural blast radius│ │
|
|
43
|
+
│ └───────────────────────────────────────────────┘ │
|
|
44
|
+
└─────────────────────────────────────────────────────────────────────────────┘
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## 2. Spanner Graph DDL (`CREATE PROPERTY GRAPH`)
|
|
50
|
+
|
|
51
|
+
Define nodes, edges, and relationship labels on top of strongly consistent Spanner tables:
|
|
52
|
+
|
|
53
|
+
```sql
|
|
54
|
+
-- 1. Base Relational Tables
|
|
55
|
+
CREATE TABLE Services (
|
|
56
|
+
service_id STRING(64) NOT NULL,
|
|
57
|
+
name STRING(128) NOT NULL,
|
|
58
|
+
tier STRING(32) NOT NULL,
|
|
59
|
+
owner_team STRING(64) NOT NULL,
|
|
60
|
+
created_at TIMESTAMP OPTIONS (allow_commit_timestamp = true)
|
|
61
|
+
) PRIMARY KEY (service_id);
|
|
62
|
+
|
|
63
|
+
CREATE TABLE Dependencies (
|
|
64
|
+
caller_id STRING(64) NOT NULL,
|
|
65
|
+
target_id STRING(64) NOT NULL,
|
|
66
|
+
protocol STRING(32) NOT NULL,
|
|
67
|
+
criticality STRING(16) NOT NULL,
|
|
68
|
+
CONSTRAINT FK_Caller FOREIGN KEY (caller_id) REFERENCES Services (service_id),
|
|
69
|
+
CONSTRAINT FK_Target FOREIGN KEY (target_id) REFERENCES Services (service_id)
|
|
70
|
+
) PRIMARY KEY (caller_id, target_id);
|
|
71
|
+
|
|
72
|
+
-- 2. Property Graph Definition (ISO GQL Standard)
|
|
73
|
+
CREATE PROPERTY GRAPH ServiceArchitectureGraph
|
|
74
|
+
VERTEX TABLES (
|
|
75
|
+
Services
|
|
76
|
+
LABEL Service
|
|
77
|
+
PROPERTIES (service_id, name, tier, owner_team)
|
|
78
|
+
)
|
|
79
|
+
EDGE TABLES (
|
|
80
|
+
Dependencies
|
|
81
|
+
SOURCE KEY (caller_id) REFERENCES Services (service_id)
|
|
82
|
+
DESTINATION KEY (target_id) REFERENCES Services (service_id)
|
|
83
|
+
LABEL CALLS
|
|
84
|
+
PROPERTIES (protocol, criticality)
|
|
85
|
+
);
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## 3. ISO GQL Graph Traversal Queries
|
|
91
|
+
|
|
92
|
+
Execute declarative graph pattern matching directly in Spanner SQL:
|
|
93
|
+
|
|
94
|
+
```sql
|
|
95
|
+
-- Multi-hop blast-radius query: Find all downstream services impacted by an outage
|
|
96
|
+
GRAPH ServiceArchitectureGraph
|
|
97
|
+
MATCH (root:Service {service_id: 'payment-gateway'})
|
|
98
|
+
-[:CALLS*1..3]-> (downstream:Service)
|
|
99
|
+
WHERE downstream.tier = 'TIER_1'
|
|
100
|
+
RETURN DISTINCT
|
|
101
|
+
root.name AS failing_service,
|
|
102
|
+
downstream.name AS impacted_dependency,
|
|
103
|
+
downstream.owner_team AS oncall_team;
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## 4. Python SDK Graph-Vector RAG Pipeline
|
|
109
|
+
|
|
110
|
+
Combines topological graph queries with Gemini reasoning to assess infrastructure change risk:
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
from google.cloud import spanner
|
|
114
|
+
from google import genai
|
|
115
|
+
|
|
116
|
+
spanner_client = spanner.Client()
|
|
117
|
+
instance = spanner_client.instance("production-instance")
|
|
118
|
+
database = instance.database("architecture-db")
|
|
119
|
+
gemini_client = genai.Client()
|
|
120
|
+
|
|
121
|
+
def analyze_architectural_blast_radius(failing_service_id: str) -> str:
|
|
122
|
+
"""Executes ISO GQL query in Spanner Graph and reasons over downstream risks with Gemini."""
|
|
123
|
+
gql_query = """
|
|
124
|
+
GRAPH ServiceArchitectureGraph
|
|
125
|
+
MATCH (s:Service {service_id: @serviceId})-[e:CALLS*1..4]->(dep:Service)
|
|
126
|
+
RETURN DISTINCT s.name AS root_service, dep.name AS dependency, dep.tier AS tier, dep.owner_team AS team
|
|
127
|
+
"""
|
|
128
|
+
|
|
129
|
+
with database.snapshot() as snapshot:
|
|
130
|
+
results = list(snapshot.execute_sql(
|
|
131
|
+
gql_query,
|
|
132
|
+
params={"serviceId": failing_service_id},
|
|
133
|
+
param_types={"serviceId": spanner.param_types.STRING}
|
|
134
|
+
))
|
|
135
|
+
|
|
136
|
+
# Format graph path topology into structured context
|
|
137
|
+
graph_context = "\n".join([
|
|
138
|
+
f"- Dependency: {row[1]} (Tier: {row[2]}, Team: {row[3]})"
|
|
139
|
+
for row in results
|
|
140
|
+
])
|
|
141
|
+
|
|
142
|
+
# Reason with Gemini using strictly grounded graph topology
|
|
143
|
+
prompt = f"""
|
|
144
|
+
The following microservice is experiencing an outage: {failing_service_id}
|
|
145
|
+
Here is the verified dependency graph topology from Spanner Graph:
|
|
146
|
+
{graph_context}
|
|
147
|
+
|
|
148
|
+
Provide an actionable incident response triage plan, identifying on-call escalations.
|
|
149
|
+
"""
|
|
150
|
+
|
|
151
|
+
response = gemini_client.models.generate_content(
|
|
152
|
+
model="gemini-2.0-flash",
|
|
153
|
+
contents=prompt
|
|
154
|
+
)
|
|
155
|
+
return response.text
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## 5. Enterprise Best Practices & Anti-Patterns
|
|
161
|
+
|
|
162
|
+
| Category | Recommended Pattern | Anti-Pattern |
|
|
163
|
+
| :--- | :--- | :--- |
|
|
164
|
+
| **Topology Modeling** | Use Directed Property Graphs with foreign keys enforcing referential integrity | Storing graph edges in unindexed JSON arrays |
|
|
165
|
+
| **Path Search Depth** | Bound variable-length path traversals (e.g. `[:CALLS*1..4]`) | Unbounded path queries (`[:CALLS*]`) causing exponential scans |
|
|
166
|
+
| **Hybrid RAG** | Retrieve exact entity graph topology from Spanner before prompt construction | Letting LLMs guess multi-hop dependencies from vector embeddings alone |
|
|
167
|
+
| **Transactions** | Execute read-only graph traversals inside Spanner read-only snapshots | Mixing long-running graph analyses into interactive read-write transactions |
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: vertex-ai-feature-store
|
|
3
|
+
description: Provisions and queries Google Cloud Vertex AI Feature Store, point-in-time correct historical joins, low-latency online serving, and Gemini embedding feature tables.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Vertex AI Feature Store & Embeddings Serving
|
|
7
|
+
|
|
8
|
+
Architects, provisions, and serves machine learning features and vector representations using Google Cloud Vertex AI Feature Store. Covers BigQuery-backed offline storage, point-in-time joins, low-latency online feature serving, and real-time agent memory retrieval.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## 1. Architecture: Vertex AI Feature Store
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
┌─────────────────────────────────────────────────────────────────────────────┐
|
|
16
|
+
│ VERTEX AI FEATURE STORE │
|
|
17
|
+
│ │
|
|
18
|
+
│ ┌─────────────────────┐ ┌───────────────────────────┐ │
|
|
19
|
+
│ │ BigQuery Lakehouse │ │ Streaming Ingestion │ │
|
|
20
|
+
│ │ (Offline Gold Data) │ │ (Pub/Sub + Dataflow) │ │
|
|
21
|
+
│ └──────────┬──────────┘ └─────────────┬─────────────┘ │
|
|
22
|
+
│ │ │ │
|
|
23
|
+
│ ▼ ▼ │
|
|
24
|
+
│ ┌─────────────────────────────────────────────────────────────────────┐ │
|
|
25
|
+
│ │ Feature Registry & View Definitions (BigQuery-backed Feature Store) │ │
|
|
26
|
+
│ │ • Entity: user_id, repo_id, session_id │ │
|
|
27
|
+
│ │ • Embeddings: text_embedding_004 (768-dim) │ │
|
|
28
|
+
│ └──────────────────┬────────────────────────────┬─────────────────────┘ │
|
|
29
|
+
│ │ │ │
|
|
30
|
+
│ ▼ Offline ▼ Online (<10ms) │
|
|
31
|
+
│ ┌─────────────────────────────┐ ┌─────────────────────────────┐ │
|
|
32
|
+
│ │ Point-in-Time Correct │ │ Optimized Online Serving │ │
|
|
33
|
+
│ │ Historical Training Joins │ │ (Bigtable / Cache Engine) │ │
|
|
34
|
+
│ └─────────────────────────────┘ └─────────────────────────────┘ │
|
|
35
|
+
└─────────────────────────────────────────────────────────────────────────────┘
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## 2. Infrastructure Provisioning (`gcloud`)
|
|
41
|
+
|
|
42
|
+
Set up a Feature Online Store optimized for sub-10ms feature retrieval:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
# 1. Create Feature Online Store with optimized serving
|
|
46
|
+
gcloud vertex-ai feature-online-stores create agent-memory-store \
|
|
47
|
+
--location=us-central1 \
|
|
48
|
+
--dedicated-serving-nodes-min=1 \
|
|
49
|
+
--dedicated-serving-nodes-max=5
|
|
50
|
+
|
|
51
|
+
# 2. Create Feature View backed by BigQuery table
|
|
52
|
+
gcloud vertex-ai feature-views create user-profile-features \
|
|
53
|
+
--feature-online-store=agent-memory-store \
|
|
54
|
+
--location=us-central1 \
|
|
55
|
+
--bigquery-table=projects/my_project/datasets/features/tables/user_profiles \
|
|
56
|
+
--entity-id-columns=user_id \
|
|
57
|
+
--cron-schedule="0 */4 * * *"
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## 3. Real-Time Online Feature Retrieval (Python SDK)
|
|
63
|
+
|
|
64
|
+
Query real-time feature vectors inside an agent execution turn:
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
from google.cloud import aiplatform_v1beta1 as vertex_ai
|
|
68
|
+
|
|
69
|
+
client = vertex_ai.FeatureOnlineStoreServiceClient()
|
|
70
|
+
|
|
71
|
+
def fetch_agent_session_features(user_id: str) -> dict:
|
|
72
|
+
"""Fetches real-time developer context and historical preference vectors."""
|
|
73
|
+
feature_view_path = client.feature_view_path(
|
|
74
|
+
project="my_project",
|
|
75
|
+
location="us-central1",
|
|
76
|
+
feature_online_store="agent-memory-store",
|
|
77
|
+
feature_view="user-profile-features"
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
response = client.fetch_feature_values(
|
|
81
|
+
request=vertex_ai.FetchFeatureValuesRequest(
|
|
82
|
+
feature_view=feature_view_path,
|
|
83
|
+
data_key=vertex_ai.FeatureViewDataKey(key=user_id)
|
|
84
|
+
)
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
return {
|
|
88
|
+
field.name: field.value
|
|
89
|
+
for field in response.key_values.features
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## 4. Point-in-Time Correct Offline Joins
|
|
96
|
+
|
|
97
|
+
Avoid data leakage in offline agent evaluation benchmarks:
|
|
98
|
+
|
|
99
|
+
```sql
|
|
100
|
+
SELECT
|
|
101
|
+
observations.task_id,
|
|
102
|
+
observations.timestamp,
|
|
103
|
+
features.seniority_level,
|
|
104
|
+
features.preferred_framework,
|
|
105
|
+
features.embedding_vector
|
|
106
|
+
FROM `my_project.evals.agent_runs` AS observations
|
|
107
|
+
POINT_IN_TIME JOIN `my_project.features.user_profiles` AS features
|
|
108
|
+
ON observations.user_id = features.user_id
|
|
109
|
+
AND observations.timestamp >= features.feature_timestamp;
|
|
110
|
+
```
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: webrtc-agent-gateway
|
|
3
|
+
description: Architect and deploy ultra-low latency WebRTC audio duplex gateways, Opus audio transcoding, STUN/TURN ICE candidate negotiation, and real-time voice streaming for Gemini Live pair programming.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# WebRTC Agent Gateway (Ultra-Low Latency Duplex Voice Streaming)
|
|
7
|
+
|
|
8
|
+
Architects, secures, and deploys production-grade WebRTC media gateways that bridge browser/IDE client media streams directly into the Google Gemini Live API. Implements bidirectional Opus/PCM audio transcoding, interactive data channels, STUN/TURN NAT traversal, and jitter-buffer optimization for sub-200ms voice pair-programming.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## 1. WebRTC Duplex Architecture
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
┌─────────────────────────────────────────────────────────────────────────────┐
|
|
16
|
+
│ WEBRTC MEDIA GATEWAY TOPOLOGY │
|
|
17
|
+
│ │
|
|
18
|
+
│ ┌─────────────────────┐ WebRTC PeerConnection ┌────────────────┐ │
|
|
19
|
+
│ │ Developer Browser │◄──────────────────────────────►│ WebRTC Gateway │ │
|
|
20
|
+
│ │ / Antigravity IDE │ SRTP / Opus Audio Tracks │ (aiortc / Go) │ │
|
|
21
|
+
│ └─────────────────────┘ SCTP DataChannel (Events) └───────┬────────┘ │
|
|
22
|
+
│ │ │ │
|
|
23
|
+
│ │ SDP Offer / Answer (HTTPS / WSS) │ │
|
|
24
|
+
│ ▼ ▼ │
|
|
25
|
+
│ ┌─────────────────────┐ ┌────────────────────┐ │
|
|
26
|
+
│ │ Coturn STUN / TURN │ │ Google Gemini Live │ │
|
|
27
|
+
│ │ NAT Traversal Relay │ │ WebSocket Endpoint │ │
|
|
28
|
+
│ └─────────────────────┘ └────────────────────┘ │
|
|
29
|
+
└─────────────────────────────────────────────────────────────────────────────┘
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## 2. Python aiortc WebRTC Gateway Implementation
|
|
35
|
+
|
|
36
|
+
Below is a production-grade WebRTC audio bridge receiving developer microphone tracks, transcoding Opus to PCM 16kHz for Gemini Live, and streaming back synthesized agent speech:
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
import asyncio
|
|
40
|
+
import json
|
|
41
|
+
import fractions
|
|
42
|
+
import time
|
|
43
|
+
from aiortc import RTCPeerConnection, RTCSessionDescription, MediaStreamTrack
|
|
44
|
+
from aiortc.contrib.media import MediaBlackhole
|
|
45
|
+
from av import AudioResampler, AudioFrame
|
|
46
|
+
from google import genai
|
|
47
|
+
from google.genai import types
|
|
48
|
+
|
|
49
|
+
class GeminiLiveAudioTrack(MediaStreamTrack):
|
|
50
|
+
"""Generates outgoing WebRTC audio frames from Gemini Live synthesized speech."""
|
|
51
|
+
kind = "audio"
|
|
52
|
+
|
|
53
|
+
def __init__(self):
|
|
54
|
+
super().__init__()
|
|
55
|
+
self.queue = asyncio.Queue()
|
|
56
|
+
self._sample_rate = 48000
|
|
57
|
+
self._samples_per_frame = 960 # 20ms at 48kHz
|
|
58
|
+
self._pts = 0
|
|
59
|
+
|
|
60
|
+
def push_pcm_bytes(self, pcm_data: bytes):
|
|
61
|
+
"""Pushes raw 24kHz/16kHz PCM audio bytes from Gemini into the WebRTC audio queue."""
|
|
62
|
+
self.queue.put_nowait(pcm_data)
|
|
63
|
+
|
|
64
|
+
async def recv(self):
|
|
65
|
+
pcm_chunk = await self.queue.get()
|
|
66
|
+
frame = AudioFrame(format="s16", layout="mono", samples=self._samples_per_frame)
|
|
67
|
+
frame.planes[0].update(pcm_chunk[:frame.linesizes[0]])
|
|
68
|
+
frame.sample_rate = self._sample_rate
|
|
69
|
+
frame.time_base = fractions.Fraction(1, self._sample_rate)
|
|
70
|
+
frame.pts = self._pts
|
|
71
|
+
self._pts += self._samples_per_frame
|
|
72
|
+
return frame
|
|
73
|
+
|
|
74
|
+
class WebRTCAgentGateway:
|
|
75
|
+
def __init__(self, gemini_api_key: str):
|
|
76
|
+
self.client = genai.Client(api_key=gemini_api_key)
|
|
77
|
+
self.pcs = set()
|
|
78
|
+
|
|
79
|
+
async def handle_offer(self, sdp_offer: str, sdp_type: str = "offer") -> dict:
|
|
80
|
+
pc = RTCPeerConnection()
|
|
81
|
+
self.pcs.add(pc)
|
|
82
|
+
|
|
83
|
+
outgoing_audio = GeminiLiveAudioTrack()
|
|
84
|
+
pc.addTrack(outgoing_audio)
|
|
85
|
+
|
|
86
|
+
@pc.on("track")
|
|
87
|
+
def on_track(track):
|
|
88
|
+
if track.kind == "audio":
|
|
89
|
+
asyncio.create_task(self._relay_to_gemini(track, outgoing_audio))
|
|
90
|
+
|
|
91
|
+
@pc.on("connectionstatechange")
|
|
92
|
+
async def on_connectionstatechange():
|
|
93
|
+
if pc.connectionState in ["failed", "closed"]:
|
|
94
|
+
await pc.close()
|
|
95
|
+
self.pcs.discard(pc)
|
|
96
|
+
|
|
97
|
+
offer = RTCSessionDescription(sdp=sdp_offer, type=sdp_type)
|
|
98
|
+
await pc.setRemoteDescription(offer)
|
|
99
|
+
answer = await pc.createAnswer()
|
|
100
|
+
await pc.setLocalDescription(answer)
|
|
101
|
+
|
|
102
|
+
return {"sdp": pc.localDescription.sdp, "type": pc.localDescription.type}
|
|
103
|
+
|
|
104
|
+
async def _relay_to_gemini(self, track: MediaStreamTrack, outgoing_audio: GeminiLiveAudioTrack):
|
|
105
|
+
resampler = AudioResampler(format="s16", layout="mono", rate=16000)
|
|
106
|
+
async with self.client.aio.live.connect(
|
|
107
|
+
model="gemini-2.0-flash-exp",
|
|
108
|
+
config=types.LiveConnectConfig(
|
|
109
|
+
response_modalities=[types.LiveModality.AUDIO],
|
|
110
|
+
speech_config=types.SpeechConfig(
|
|
111
|
+
voice_config=types.VoiceConfig(
|
|
112
|
+
prebuilt_voice_config=types.PrebuiltVoiceConfig(voice_name="Aoede")
|
|
113
|
+
)
|
|
114
|
+
)
|
|
115
|
+
)
|
|
116
|
+
) as session:
|
|
117
|
+
# Task to read synthesized audio from Gemini and queue to WebRTC
|
|
118
|
+
async def receive_from_gemini():
|
|
119
|
+
async for response in session.receive():
|
|
120
|
+
server_content = response.server_content
|
|
121
|
+
if server_content and server_content.model_turn:
|
|
122
|
+
for part in server_content.model_turn.parts:
|
|
123
|
+
if part.inline_data:
|
|
124
|
+
outgoing_audio.push_pcm_bytes(part.inline_data.data)
|
|
125
|
+
|
|
126
|
+
receiver_task = asyncio.create_task(receive_from_gemini())
|
|
127
|
+
|
|
128
|
+
try:
|
|
129
|
+
while True:
|
|
130
|
+
frame = await track.recv()
|
|
131
|
+
resampled = resampler.resample(frame)
|
|
132
|
+
for r_frame in resampled:
|
|
133
|
+
pcm_bytes = r_frame.planes[0].to_bytes()
|
|
134
|
+
await session.send(input={"data": pcm_bytes, "mime_type": "audio/pcm;rate=16000"})
|
|
135
|
+
except asyncio.CancelledError:
|
|
136
|
+
receiver_task.cancel()
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## 3. Client WebRTC SDP Exchange & ICE Configuration
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
export async function initializeVoiceSession(gatewayUrl: string): Promise<RTCPeerConnection> {
|
|
145
|
+
const pc = new RTCPeerConnection({
|
|
146
|
+
iceServers: [
|
|
147
|
+
{ urls: 'stun:stun.l.google.com:19302' },
|
|
148
|
+
{
|
|
149
|
+
urls: 'turn:turn.enterprise-antigravity.internal:3478',
|
|
150
|
+
username: 'agent-dev',
|
|
151
|
+
credential: 'ephemeral-turn-token'
|
|
152
|
+
}
|
|
153
|
+
]
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
// Capture developer microphone stream
|
|
157
|
+
const micStream = await navigator.mediaDevices.getUserMedia({
|
|
158
|
+
audio: {
|
|
159
|
+
channelCount: 1,
|
|
160
|
+
sampleRate: 48000,
|
|
161
|
+
echoCancellation: true,
|
|
162
|
+
noiseSuppression: true,
|
|
163
|
+
autoGainControl: true
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
micStream.getAudioTracks().forEach(track => pc.addTrack(track, micStream));
|
|
168
|
+
|
|
169
|
+
// Audio track speaker output
|
|
170
|
+
pc.ontrack = (event) => {
|
|
171
|
+
if (event.track.kind === 'audio') {
|
|
172
|
+
const audioEl = new Audio();
|
|
173
|
+
audioEl.srcObject = event.streams[0];
|
|
174
|
+
audioEl.play().catch(console.error);
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
const offer = await pc.createOffer();
|
|
179
|
+
await pc.setLocalDescription(offer);
|
|
180
|
+
|
|
181
|
+
const response = await fetch(`${gatewayUrl}/api/webrtc/offer`, {
|
|
182
|
+
method: 'POST',
|
|
183
|
+
headers: { 'Content-Type': 'application/json' },
|
|
184
|
+
body: JSON.stringify({ sdp: offer.sdp, type: offer.type })
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
const answer = await response.json();
|
|
188
|
+
await pc.setRemoteDescription(new RTCSessionDescription(answer));
|
|
189
|
+
return pc;
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## 4. Operational Best Practices & SLA Targets
|
|
196
|
+
|
|
197
|
+
1. **Jitter-Buffer Tuning**: Target 40ms to 80ms playout delay. Avoid buffer bloating which degrades conversational turn-taking.
|
|
198
|
+
2. **STUN/TURN High Availability**: Deploy Coturn behind Network Load Balancers (NLB) across at least 2 GCP availability zones.
|
|
199
|
+
3. **Graceful Teardown**: Intercept `connectionstatechange` to immediately close Gemini WebSocket sessions on client hangup.
|