MCPcopy Create free account
hub / github.com/agentforce314/clawcodex / TranscriptWriter

Class TranscriptWriter

src/agent/transcript.py:157–235  ·  view source on GitHub ↗

Append-only writer for the JSONL transcript at ``path``. Opens an ``O_APPEND`` file descriptor on construction. Each ``append(message)`` call serializes one line and emits it via a single ``os.write`` so concurrent writers (e.g. the same agent across crash-restart, or a future multi

Source from the content-addressed store, hash-verified

155
156
157class TranscriptWriter:
158 """Append-only writer for the JSONL transcript at ``path``.
159
160 Opens an ``O_APPEND`` file descriptor on construction. Each
161 ``append(message)`` call serializes one line and emits it via a
162 single ``os.write`` so concurrent writers (e.g. the same agent
163 across crash-restart, or a future multi-writer scenario) cannot
164 interleave bytes at sub-PIPE_BUF line sizes.
165
166 The writer is **synchronous** (file IO, not asyncio). Per the A6/C5
167 contract, callers must NOT hold ``RuntimeTaskRegistry``'s RLock
168 across an ``append()`` call: while file IO is fast, blocking under
169 the registry's lock would deadlock the asyncio scheduler against
170 bash worker threads.
171 """
172
173 def __init__(self, path: str | Path) -> None:
174 self._path = str(path)
175 # Ensure parent dir exists (transcript root may not have been
176 # created yet if the caller bypassed ``get_agent_transcript_path``).
177 Path(self._path).parent.mkdir(parents=True, exist_ok=True)
178 # ``O_APPEND`` makes every write atomic at the file-position
179 # level. ``O_CLOEXEC`` keeps the fd from leaking to bash
180 # subprocesses. ``0o600`` because transcripts can contain
181 # sensitive prompt content — readable by the user only.
182 self._fd: int | None = os.open(
183 self._path,
184 os.O_WRONLY | os.O_APPEND | os.O_CREAT | os.O_CLOEXEC,
185 0o600,
186 )
187 self._closed = False
188
189 @property
190 def path(self) -> str:
191 return self._path
192
193 def append(self, message: Any) -> None:
194 """Append one message as a UTF-8 JSON line, terminated with ``\\n``.
195
196 Crash-safety: a single ``os.write`` of the line ensures the
197 writer either appends the whole line or nothing. POSIX
198 guarantees this for sizes ≤ ``PIPE_BUF`` (≥4096 bytes on every
199 modern Unix); for larger lines the reader is tolerant of
200 partial trailing content per the JSONL format design.
201 """
202 if self._closed or self._fd is None:
203 raise RuntimeError("TranscriptWriter is closed")
204 line = _serialize_message(message) + "\n"
205 encoded = line.encode("utf-8")
206 # ``os.write`` may short-write under specific OS conditions;
207 # loop until the whole buffer is on disk. For O_APPEND files
208 # the returned ``n`` is byte count of THIS write, so the loop
209 # is straightforward.
210 view = memoryview(encoded)
211 while view:
212 written = os.write(self._fd, view)
213 if written <= 0:
214 # Defensive: 0-byte returns shouldn't happen on regular

Calls

no outgoing calls