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

Method enrich_opencode_turn

atomic-agent/src/turn/orchestrator/provenance.rs:336–484  ·  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

334 /// journal then commits the enriched terminal envelopes.
335 ///
336 pub(crate) fn enrich_opencode_turn(
337 &self,
338 session: &mut AgentSession,
339 event: &mut TurnEvent,
340 ) -> AgentResult<()> {
341 if session.agent_name != "opencode" {
342 return Ok(());
343 }
344
345 let Some(data) = transcript::opencode::read_turn(&session.session_id, &self.repo_root)
346 else {
347 return Ok(());
348 };
349
350 // 1. Transcript file → transcript_path (unblocks agent_turn).
351 // Rewritten on every turn (whole-session record); a plugin-supplied
352 // transcript path is never clobbered.
353 if !data.transcript_jsonl.is_empty() {
354 let dir = self.session_graph_dir(&session.session_id);
355 let synthesized = dir.join("opencode-transcript.jsonl");
356 let ours = session.transcript_path.is_none()
357 || session.transcript_path.as_deref() == Some(synthesized.as_path());
358 if ours {
359 let _ = std::fs::create_dir_all(&dir);
360 match std::fs::write(&synthesized, &data.transcript_jsonl) {
361 Ok(()) => session.set_transcript_path(&synthesized),
362 Err(e) => log::warn!(
363 "Failed to write opencode transcript for session {}: {}",
364 session.session_id,
365 e
366 ),
367 }
368 }
369 }
370
371 // 2. Stop-payload fields the plugin didn't send.
372 let Some(raw) = event.raw_json.as_mut() else {
373 return Ok(());
374 };
375 let Some(obj) = raw.as_object_mut() else {
376 return Ok(());
377 };
378
379 if !obj.contains_key("reasoning_blocks")
380 && !obj.contains_key("reasoning_text")
381 && !data.reasoning_blocks.is_empty()
382 {
383 let blocks: Vec<serde_json::Value> = data
384 .reasoning_blocks
385 .iter()
386 .map(|b| {
387 serde_json::json!({
388 "text": b.text,
389 "duration_ms": b.duration_ms,
390 })
391 })
392 .collect();
393 obj.insert(

Callers 1

handle_turn_endMethod · 0.80

Calls 12

read_turnFunction · 0.85
writeFunction · 0.85
stable_journal_idFunction · 0.85
session_graph_dirMethod · 0.80
is_noneMethod · 0.80
set_transcript_pathMethod · 0.80
contains_keyMethod · 0.80
commit_journal_draftsMethod · 0.80
is_emptyMethod · 0.45
iterMethod · 0.45
insertMethod · 0.45
cloneMethod · 0.45

Tested by

no test coverage detected