Skip to content

Commit 12ad547

Browse files
Gkrumbach07Ambient Code Botclaude
authored
fix(runner): add timestamps to Gemini CLI messages in UI (#892)
## Summary - Pass event timestamps from Gemini CLI NDJSON to AguiAssistantMessage objects - Converts ISO timestamps to milliseconds for AG-UI compatibility - Adds timestamps to TextMessageStartEvent for streaming events ## Test plan - [x] Unit tests pass (13/13 Gemini adapter tests) - [x] Lints pass (ruff check + ruff format) - [ ] Manual test: start Gemini session, verify timestamps appear Fixes: RHOAIENG-52261 **Jira:** [RHOAIENG-52261](https://issues.redhat.com/browse/RHOAIENG-52261) Co-authored-by: Ambient Code Bot <bot@ambient-code.local> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 310e369 commit 12ad547

1 file changed

Lines changed: 21 additions & 0 deletions

File tree

  • components/runners/ambient-runner/ag_ui_gemini_cli

components/runners/ambient-runner/ag_ui_gemini_cli/adapter.py

100644100755
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import json
88
import logging
99
import uuid
10+
from datetime import datetime
1011
from typing import AsyncIterator, Optional
1112

1213
from ag_ui.core import (
@@ -40,6 +41,15 @@
4041
logger = logging.getLogger(__name__)
4142

4243

44+
def _iso_to_ms(iso_timestamp: str) -> Optional[int]:
45+
"""Convert an ISO 8601 timestamp string to epoch milliseconds."""
46+
try:
47+
dt = datetime.fromisoformat(iso_timestamp.replace("Z", "+00:00"))
48+
return int(dt.timestamp() * 1000)
49+
except (ValueError, AttributeError):
50+
return None
51+
52+
4353
def _summarize_event(event: object) -> str:
4454
"""One-line summary of a Gemini CLI event for logging."""
4555
if isinstance(event, InitEvent):
@@ -88,6 +98,7 @@ async def run(
8898
text_message_open = False
8999
current_message_id: Optional[str] = None
90100
accumulated_text = ""
101+
message_timestamp_ms: Optional[int] = None
91102

92103
# Tool tracking
93104
current_tool_call_id: Optional[str] = None
@@ -141,10 +152,12 @@ async def run(
141152
# First text chunk: open a text message
142153
if not text_message_open:
143154
current_message_id = str(uuid.uuid4())
155+
message_timestamp_ms = _iso_to_ms(event.timestamp)
144156
yield TextMessageStartEvent(
145157
type=EventType.TEXT_MESSAGE_START,
146158
message_id=current_message_id,
147159
role="assistant",
160+
timestamp=message_timestamp_ms,
148161
)
149162
text_message_open = True
150163
accumulated_text = ""
@@ -163,10 +176,12 @@ async def run(
163176
if event.role == "assistant" and not event.delta:
164177
if not text_message_open:
165178
current_message_id = str(uuid.uuid4())
179+
message_timestamp_ms = _iso_to_ms(event.timestamp)
166180
yield TextMessageStartEvent(
167181
type=EventType.TEXT_MESSAGE_START,
168182
message_id=current_message_id,
169183
role="assistant",
184+
timestamp=message_timestamp_ms,
170185
)
171186
text_message_open = True
172187
accumulated_text = ""
@@ -193,10 +208,12 @@ async def run(
193208
id=current_message_id,
194209
role="assistant",
195210
content=accumulated_text,
211+
timestamp=message_timestamp_ms,
196212
)
197213
)
198214
current_message_id = None
199215
accumulated_text = ""
216+
message_timestamp_ms = None
200217
continue
201218

202219
# ── tool_use ──
@@ -213,11 +230,13 @@ async def run(
213230
id=current_message_id,
214231
role="assistant",
215232
content=accumulated_text,
233+
timestamp=message_timestamp_ms,
216234
)
217235
)
218236
text_message_open = False
219237
current_message_id = None
220238
accumulated_text = ""
239+
message_timestamp_ms = None
221240

222241
current_tool_call_id = event.tool_id or str(uuid.uuid4())
223242
yield ToolCallStartEvent(
@@ -297,11 +316,13 @@ async def run(
297316
id=current_message_id,
298317
role="assistant",
299318
content=accumulated_text,
319+
timestamp=message_timestamp_ms,
300320
)
301321
)
302322
text_message_open = False
303323
current_message_id = None
304324
accumulated_text = ""
325+
message_timestamp_ms = None
305326

306327
if event.status == "error":
307328
error_msg = "Gemini CLI run failed"

0 commit comments

Comments
 (0)