Skip to main content

agent_first_http/sdk/fetch/artifacts/
console.rs

1//! Console event capture (`console.json`) via CDP
2//! `Runtime.consoleAPICalled` + `Runtime.exceptionThrown`.
3
4use std::path::PathBuf;
5
6use serde::{Deserialize, Serialize};
7
8use crate::sdk::fetch::writer;
9use crate::shared::artifacts::{Artifact, ArtifactPaths};
10use crate::shared::error::{Error, ErrorCode};
11
12pub const CONSOLE_SCHEMA_VERSION: u32 = 2;
13
14#[derive(Debug, Clone, Serialize, Deserialize)]
15pub struct ConsoleLog {
16    pub schema_version: u32,
17    pub events: Vec<ConsoleEvent>,
18}
19
20#[derive(Debug, Clone, Serialize, Deserialize)]
21pub struct ConsoleEvent {
22    pub level: ConsoleLevel,
23    #[serde(alias = "timestamp_ms")]
24    pub timestamp_epoch_ms: f64,
25    pub text: String,
26    #[serde(skip_serializing_if = "Option::is_none")]
27    #[serde(alias = "url")]
28    pub source_url: Option<String>,
29    #[serde(skip_serializing_if = "Option::is_none")]
30    pub line_number: Option<u32>,
31}
32
33#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
34#[serde(rename_all = "snake_case")]
35pub enum ConsoleLevel {
36    Log,
37    Debug,
38    Info,
39    Warn,
40    Error,
41    Exception,
42}
43
44pub async fn write(paths: &ArtifactPaths, log: &ConsoleLog) -> Result<PathBuf, Error> {
45    let target = paths.file_for(Artifact::Console);
46    let bytes = serde_json::to_vec_pretty(log).map_err(|e| {
47        Error::new(
48            ErrorCode::InternalError,
49            format!("serialize console log: {e}"),
50        )
51    })?;
52    writer::write_bytes(&target, &bytes).await?;
53    Ok(target)
54}