|
11 | 11 | from typing import List, Literal, Optional |
12 | 12 |
|
13 | 13 | from openviking.message.part import ContextPart, Part, TextPart, ToolPart |
14 | | -from openviking.utils.time_utils import format_iso8601, parse_iso_datetime |
15 | 14 |
|
16 | 15 |
|
17 | 16 | @dataclass |
@@ -65,6 +64,12 @@ def estimated_tokens(self) -> int: |
65 | 64 | def to_dict(self) -> dict: |
66 | 65 | """Serialize to JSONL.""" |
67 | 66 | created_at_val = self.created_at or datetime.now(timezone.utc).isoformat() |
| 67 | + if isinstance(created_at_val, datetime): |
| 68 | + created_at_val = ( |
| 69 | + created_at_val.astimezone(timezone.utc) |
| 70 | + .isoformat(timespec="milliseconds") |
| 71 | + .replace("+00:00", "Z") |
| 72 | + ) |
68 | 73 | return { |
69 | 74 | "id": self.id, |
70 | 75 | "role": self.role, |
@@ -108,7 +113,15 @@ def _part_to_dict(self, part: Part) -> dict: |
108 | 113 | def from_dict(cls, data: dict) -> "Message": |
109 | 114 | """Deserialize from JSONL.""" |
110 | 115 | parts = [] |
111 | | - for p in data.get("parts", []): |
| 116 | + raw_parts = data.get("parts") |
| 117 | + if raw_parts is None: |
| 118 | + legacy_content = data.get("content") |
| 119 | + if legacy_content is not None: |
| 120 | + raw_parts = [{"type": "text", "text": legacy_content}] |
| 121 | + else: |
| 122 | + raw_parts = [] |
| 123 | + |
| 124 | + for p in raw_parts: |
112 | 125 | if p["type"] == "text": |
113 | 126 | parts.append(TextPart(text=p.get("text", ""))) |
114 | 127 | elif p["type"] == "context": |
@@ -138,7 +151,7 @@ def from_dict(cls, data: dict) -> "Message": |
138 | 151 | id=data["id"], |
139 | 152 | role=data["role"], |
140 | 153 | parts=parts, |
141 | | - created_at=data["created_at"], |
| 154 | + created_at=data.get("created_at"), |
142 | 155 | ) |
143 | 156 |
|
144 | 157 | @classmethod |
@@ -193,7 +206,7 @@ def create_assistant( |
193 | 206 | id=msg_id or f"msg_{uuid4().hex}", |
194 | 207 | role="assistant", |
195 | 208 | parts=parts, |
196 | | - created_at=datetime.now(timezone.utc).isoformat() |
| 209 | + created_at=datetime.now(timezone.utc).isoformat(), |
197 | 210 | ) |
198 | 211 |
|
199 | 212 | def get_context_parts(self) -> List[ContextPart]: |
|
0 commit comments