| 1 | package transcript |
| 2 | |
| 3 | import ( |
| 4 | "errors" |
| 5 | "reasonix/internal/event" |
| 6 | "reasonix/internal/eventwire" |
| 7 | "reasonix/internal/provider" |
| 8 | "reasonix/internal/turnevent" |
| 9 | ) |
| 10 | |
| 11 | func EventFromEnvelope(envelope turnevent.Envelope) (event.Event, bool) { |
| 12 | w := envelope.Event |
| 13 | e := event.Event{ |
| 14 | MessageID: w.MessageID, AttemptID: w.AttemptID, |
| 15 | TurnID: envelope.TurnID, Sequence: envelope.Sequence, Status: envelope.Status, |
| 16 | Text: w.Text, Detail: w.Detail, Reasoning: w.Reasoning, ItemID: envelope.ItemID, Source: envelope.Source, |
| 17 | } |
| 18 | switch envelope.Kind { |
| 19 | case "user_message": |
| 20 | e.Kind = event.UserMessage |
| 21 | case "stream_attempt": |
| 22 | e.Kind = event.StreamAttempt |
| 23 | if w.StreamAttempt != nil { |
| 24 | e.StreamAttempt = event.StreamAttemptInfo{ID: w.StreamAttempt.ID, Action: event.StreamAttemptAction(w.StreamAttempt.Action), Attempt: w.StreamAttempt.Attempt, Max: w.StreamAttempt.Max, Reason: w.StreamAttempt.Reason} |
| 25 | } |
| 26 | case "phase": |
| 27 | e.Kind = event.Phase |
| 28 | case "reasoning": |
| 29 | e.Kind = event.Reasoning |
| 30 | case "text": |
| 31 | e.Kind = event.Text |
| 32 | case "message": |
| 33 | e.Kind = event.Message |
| 34 | case "tool_dispatch": |
| 35 | e.Kind = event.ToolDispatch |
| 36 | case "tool_result": |
| 37 | e.Kind = event.ToolResult |
| 38 | case "notice": |
| 39 | e.Kind = event.Notice |
| 40 | case "completion_summary": |
| 41 | e.Kind = event.CompletionSummary |
| 42 | if w.Completion != nil { |
| 43 | c := w.Completion |
| 44 | e.Completion = &event.CompletionSummaryInfo{Preset: c.Preset, Verdict: c.Verdict, Mutations: c.Mutations, ChecksPassed: c.ChecksPassed, ChecksFailed: c.ChecksFailed, ChecksSuppressed: c.ChecksSuppressed, Review: c.Review, GapKinds: c.GapKinds, ConstraintDegraded: c.ConstraintDegraded, Floor: c.Floor, Attention: c.Attention} |
| 45 | } |
| 46 | case "turn_done": |
| 47 | e.Kind = event.TurnDone |
| 48 | e.Receipt = eventwire.CompletionReceiptEvent(w.Receipt) |
| 49 | e.CheckpointTurn = w.CheckpointTurn |
| 50 | e.Outcome, e.ReadPause, e.ProtocolRecovery, e.Diagnostic, e.Recovery = w.Outcome, w.ReadPause, w.ProtocolRecovery, w.Diagnostic, w.Recovery |
| 51 | e.ReadCompletion = w.ReadCompletion |
| 52 | if w.Err != "" { |
| 53 | e.Err = errors.New(w.Err) |
| 54 | } |
| 55 | if w.Readiness != nil { |
| 56 | e.Readiness = &event.FinalReadiness{Attempts: w.Readiness.Attempts, Missing: w.Readiness.Missing} |
| 57 | } |
| 58 | default: |
| 59 | return event.Event{}, false |
| 60 | } |
| 61 | if w.Level == "warn" { |
| 62 | e.Level = event.LevelWarn |
| 63 | } |
| 64 | e.Code = w.Code |
| 65 | if w.Tool != nil { |
| 66 | e.Tool = event.Tool{ |
| 67 | ID: w.Tool.ID, Name: w.Tool.Name, Args: w.Tool.Args, ResolvedName: w.Tool.ResolvedName, |
| 68 | CapabilityID: w.Tool.CapabilityID, Output: w.Tool.Output, Err: w.Tool.Err, |
| 69 | ReadOnly: w.Tool.ReadOnly, Truncated: w.Tool.Truncated, DurationMs: w.Tool.DurationMs, |
| 70 | StartedAt: w.Tool.StartedAt, EndedAt: w.Tool.EndedAt, Partial: w.Tool.Partial, |
| 71 | ArgChars: w.Tool.ArgChars, Refreshed: w.Tool.Refreshed, ParentID: w.Tool.ParentID, |
| 72 | AttemptID: w.Tool.AttemptID, FileDiff: event.FileDiff{Diff: w.Tool.Diff, Added: w.Tool.Added, Removed: w.Tool.Removed}, |
| 73 | SubagentRef: w.Tool.SubagentRef, SubagentStatus: w.Tool.SubagentStatus, |
| 74 | SubagentErrorCode: w.Tool.SubagentErrorCode, SubagentRetryable: w.Tool.SubagentRetryable, |
| 75 | PresentedFiles: append([]provider.PresentedFile(nil), w.Tool.PresentedFiles...), |
| 76 | } |
| 77 | } |
| 78 | if len(w.MemoryCitations) > 0 { |
| 79 | e.MemoryCitations = make([]provider.MemoryCitation, 0, len(w.MemoryCitations)) |
| 80 | for _, citation := range w.MemoryCitations { |
| 81 | e.MemoryCitations = append(e.MemoryCitations, provider.MemoryCitation{ |
| 82 | ID: citation.ID, Source: citation.Source, LineStart: citation.LineStart, |
| 83 | LineEnd: citation.LineEnd, Note: citation.Note, Kind: citation.Kind, |
| 84 | }) |
| 85 | } |
| 86 | } |
| 87 | if w.DecisionReceipt != nil { |
| 88 | e.DecisionReceipt = &provider.DecisionReceipt{ |
| 89 | ID: w.DecisionReceipt.ID, Kind: w.DecisionReceipt.Kind, Tool: w.DecisionReceipt.Tool, |
| 90 | Subject: w.DecisionReceipt.Subject, Outcome: w.DecisionReceipt.Outcome, |
| 91 | } |
| 92 | } |
| 93 | return e, true |
| 94 | } |
| 95 |