(content: string)
| 151 | } |
| 152 | |
| 153 | function parseOpenCodeLog(content: string): ExtractedTrajectory { |
| 154 | const steps: TrajectoryStep[] = []; |
| 155 | for (const line of content.split('\n')) { |
| 156 | if (!line.trim()) continue; |
| 157 | if (line.startsWith('[kimi-loop]') || line.startsWith('[opencode-loop]')) { |
| 158 | steps.push({ source: 'agent', text: line }); |
| 159 | continue; |
| 160 | } |
| 161 | try { |
| 162 | const entry = JSON.parse(line); |
| 163 | if (entry.type === 'text') { |
| 164 | const text = entry.part?.content || entry.part?.text || ''; |
| 165 | if (text) steps.push({ source: 'agent', text }); |
| 166 | } else if (entry.type === 'tool_use') { |
| 167 | const tool = entry.part?.tool || ''; |
| 168 | const input = entry.part?.state?.input || {}; |
| 169 | if (tool === 'bash') { |
| 170 | steps.push({ source: 'tool', text: `bash: ${input.command || ''}`.slice(0, 200) }); |
| 171 | } else if (tool === 'read') { |
| 172 | steps.push({ source: 'tool', text: `read: ${input.filePath || ''}` }); |
| 173 | } else if (tool === 'write') { |
| 174 | steps.push({ source: 'tool', text: `write: ${input.filePath || ''}` }); |
| 175 | } else if (tool) { |
| 176 | steps.push({ source: 'tool', text: tool }); |
| 177 | } |
| 178 | } |
| 179 | } catch {} |
| 180 | } |
| 181 | return { steps: steps.slice(0, 200) }; |
| 182 | } |
| 183 | |
| 184 | function parseGeminiCliLog(content: string): ExtractedTrajectory { |
| 185 | const steps: TrajectoryStep[] = []; |
no outgoing calls
no test coverage detected