MCPcopy Create free account
hub / github.com/atomicdotdev/atomic / enrich_opencode_turn

Method enrich_opencode_turn

atomic-agent/src/turn/orchestrator/provenance.rs:324–485  ·  view source on GitHub ↗

OpenCode: recover transcript, reasoning, and response from OpenCode's local SQLite store and fold them into the session and the stop payload before recording. OpenCode writes no transcript file, so its sessions never carry a `transcript_path`, and thin plugin versions forward only session/model metadata. Without this step an OpenCode turn could never carry `agent_turn` data, reasoning, or an `llm

(&self, session: &mut AgentSession, event: &mut TurnEvent)

Source from the content-addressed store, hash-verified

322 /// Best-effort: any failure leaves the turn recording what the plugin
323 /// sent.
324 pub(crate) fn enrich_opencode_turn(&self, session: &mut AgentSession, event: &mut TurnEvent) {
325 if session.agent_name != "opencode" {
326 return;
327 }
328
329 let Some(data) = transcript::opencode::read_turn(&session.session_id, &self.repo_root)
330 else {
331 return;
332 };
333
334 // 1. Transcript file → transcript_path (unblocks agent_turn).
335 // Rewritten on every turn (whole-session record); a plugin-supplied
336 // transcript path is never clobbered.
337 if !data.transcript_jsonl.is_empty() {
338 let dir = self.session_graph_dir(&session.session_id);
339 let synthesized = dir.join("opencode-transcript.jsonl");
340 let ours = session.transcript_path.is_none()
341 || session.transcript_path.as_deref() == Some(synthesized.as_path());
342 if ours {
343 let _ = std::fs::create_dir_all(&dir);
344 match std::fs::write(&synthesized, &data.transcript_jsonl) {
345 Ok(()) => session.set_transcript_path(&synthesized),
346 Err(e) => log::warn!(
347 "Failed to write opencode transcript for session {}: {}",
348 session.session_id,
349 e
350 ),
351 }
352 }
353 }
354
355 // 2. Stop-payload fields the plugin didn't send.
356 let Some(raw) = event.raw_json.as_mut() else {
357 return;
358 };
359 let Some(obj) = raw.as_object_mut() else {
360 return;
361 };
362
363 if !obj.contains_key("reasoning_blocks")
364 && !obj.contains_key("reasoning_text")
365 && !data.reasoning_blocks.is_empty()
366 {
367 let blocks: Vec<serde_json::Value> = data
368 .reasoning_blocks
369 .iter()
370 .map(|b| {
371 serde_json::json!({
372 "text": b.text,
373 "duration_ms": b.duration_ms,
374 })
375 })
376 .collect();
377 obj.insert(
378 "reasoning_blocks".to_string(),
379 serde_json::Value::Array(blocks),
380 );
381 }

Callers 1

handle_turn_endMethod · 0.80

Calls 15

read_turnFunction · 0.85
writeFunction · 0.85
summarize_tool_callFunction · 0.85
build_tool_detailFunction · 0.85
session_graph_dirMethod · 0.80
is_noneMethod · 0.80
set_transcript_pathMethod · 0.80
contains_keyMethod · 0.80
with_accumulatorMethod · 0.80
iter_mutMethod · 0.80
as_refMethod · 0.80
getMethod · 0.65

Tested by

no test coverage detected