Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 34 additions & 17 deletions .opencode/plugins/sce-agent-trace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { Hooks, Plugin } from "@opencode-ai/plugin";

type OpenCodeEvent = Parameters<NonNullable<Hooks["event"]>>[0]["event"];

const REQUIRED_EVENTS = new Set(["session.diff"]);
const REQUIRED_EVENTS = new Set(["message.updated"]);

const ALL_CAPTURED_EVENTS = REQUIRED_EVENTS;

Expand All @@ -15,13 +15,14 @@ type DiffTracePayload = {
sessionID: string;
diff: string;
time: number;
model_id: string;
};

function extractDiffTracePayload(
input: TraceInput,
): DiffTracePayload | undefined {
const event = input.event;
if (event === undefined || event.type !== "session.diff") {
if (event === undefined || event.type !== "message.updated") {
return undefined;
}

Expand All @@ -30,15 +31,36 @@ function extractDiffTracePayload(
return undefined;
}

const propertiesObj = properties as Record<string, unknown>;
const propertiesObj = properties;

// Access properties.info (the Message object)
const info = propertiesObj.info;
if (typeof info !== "object" || info === null) {
return undefined;
}

const infoObj = info;

// Only capture user messages (filter out assistant, system, etc.)
if (infoObj.role !== "user") {
return undefined;
}

const sessionID =
typeof propertiesObj.sessionID === "string" &&
propertiesObj.sessionID.trim().length > 0
? propertiesObj.sessionID
typeof infoObj.sessionID === "string" &&
infoObj.sessionID.trim().length > 0
? infoObj.sessionID
: "unknown";

const diffEntries = propertiesObj.diff;
const model = infoObj.model;

// Access info.summary?.diffs via explicit checks
const summary = infoObj.summary;
const diffEntries =
typeof summary === "object" && summary !== null
? (summary).diffs
: undefined;

if (!Array.isArray(diffEntries) || diffEntries.length === 0) {
return undefined;
}
Expand All @@ -48,16 +70,10 @@ function extractDiffTracePayload(
if (typeof entry !== "object" || entry === null) {
continue;
}
const entryObj = entry as Record<string, unknown>;
const patch =
typeof entryObj.patch === "string"
? entryObj.patch
: typeof entryObj.diff === "string"
? entryObj.diff
: undefined;
if (patch !== undefined && patch.trim().length > 0) {
patches.push(patch);
}
const entryObj = entry as {patch?:string};
const patch = entryObj.patch || "";

patches.push(patch);
}

if (patches.length === 0) {
Expand All @@ -68,6 +84,7 @@ function extractDiffTracePayload(
sessionID,
diff: patches.join("\n"),
time: Date.now(),
model_id: `${model.providerID}/${model.modelID}`,
};
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE diff_traces ADD COLUMN model_id TEXT;
13 changes: 11 additions & 2 deletions cli/src/services/agent_trace_db/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ const ADD_DIFF_TRACES_TIME_MS_ID_INDEX_MIGRATION: &str =
include_str!("../../../migrations/agent-trace/003_add_diff_traces_time_ms_id_index.sql");
const CREATE_AGENT_TRACES_MIGRATION: &str =
include_str!("../../../migrations/agent-trace/004_create_agent_traces.sql");
const ADD_DIFF_TRACES_MODEL_ID_MIGRATION: &str =
include_str!("../../../migrations/agent-trace/005_add_diff_traces_model_id.sql");

const AGENT_TRACE_MIGRATIONS: &[(&str, &str)] = &[
("001_create_diff_traces", CREATE_DIFF_TRACES_MIGRATION),
Expand All @@ -32,11 +34,15 @@ const AGENT_TRACE_MIGRATIONS: &[(&str, &str)] = &[
ADD_DIFF_TRACES_TIME_MS_ID_INDEX_MIGRATION,
),
("004_create_agent_traces", CREATE_AGENT_TRACES_MIGRATION),
(
"005_add_diff_traces_model_id",
ADD_DIFF_TRACES_MODEL_ID_MIGRATION,
),
];

/// Parameterized SQL for inserting a captured diff trace payload.
pub const INSERT_DIFF_TRACE_SQL: &str =
"INSERT INTO diff_traces (time_ms, session_id, patch) VALUES (?1, ?2, ?3)";
"INSERT INTO diff_traces (time_ms, session_id, patch, model_id) VALUES (?1, ?2, ?3, ?4)";

/// Parameterized SQL for retrieving recent captured diff trace patches.
pub const SELECT_RECENT_DIFF_TRACE_PATCHES_SQL: &str = "SELECT id, time_ms, session_id, patch
Expand Down Expand Up @@ -86,6 +92,7 @@ pub struct DiffTraceInsert<'a> {
pub time_ms: i64,
pub session_id: &'a str,
pub patch: &'a str,
pub model_id: &'a str,
}

/// Raw diff trace row read from the agent trace database.
Expand Down Expand Up @@ -188,7 +195,7 @@ impl AgentTraceDb {
fn insert_diff_trace_with<M: DbSpec>(db: &TursoDb<M>, input: DiffTraceInsert<'_>) -> Result<u64> {
db.execute(
INSERT_DIFF_TRACE_SQL,
(input.time_ms, input.session_id, input.patch),
(input.time_ms, input.session_id, input.patch, input.model_id),
)
}

Expand Down Expand Up @@ -365,6 +372,7 @@ mod tests {
time_ms,
session_id,
patch,
model_id: "test-provider/test-model",
},
)
.expect("diff trace insert should succeed");
Expand Down Expand Up @@ -510,6 +518,7 @@ mod tests {
"002_create_post_commit_patch_intersections",
"003_add_diff_traces_time_ms_id_index",
"004_create_agent_traces",
"005_add_diff_traces_model_id",
]
);
}
Expand Down
4 changes: 4 additions & 0 deletions cli/src/services/hooks/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ struct DiffTracePayload {
session_id: String,
diff: String,
time: u64,
model_id: String,
}

pub fn run_hooks_subcommand(
Expand Down Expand Up @@ -147,11 +148,13 @@ fn parse_diff_trace_payload(stdin_payload: &str) -> Result<DiffTracePayload> {
let session_id = required_non_empty_string_field(payload, "sessionID")?;
let diff = required_non_empty_string_field(payload, "diff")?;
let time = required_u64_millisecond_field(payload, "time")?;
let model_id = required_non_empty_string_field(payload, "model_id")?;

Ok(DiffTracePayload {
session_id,
diff,
time,
model_id,
})
}

Expand Down Expand Up @@ -282,6 +285,7 @@ where
time_ms,
session_id: &payload.session_id,
patch: &payload.diff,
model_id: &payload.model_id,
})
}

Expand Down
51 changes: 34 additions & 17 deletions config/.opencode/plugins/sce-agent-trace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { Hooks, Plugin } from "@opencode-ai/plugin";

type OpenCodeEvent = Parameters<NonNullable<Hooks["event"]>>[0]["event"];

const REQUIRED_EVENTS = new Set(["session.diff"]);
const REQUIRED_EVENTS = new Set(["message.updated"]);

const ALL_CAPTURED_EVENTS = REQUIRED_EVENTS;

Expand All @@ -15,13 +15,14 @@ type DiffTracePayload = {
sessionID: string;
diff: string;
time: number;
model_id: string;
};

function extractDiffTracePayload(
input: TraceInput,
): DiffTracePayload | undefined {
const event = input.event;
if (event === undefined || event.type !== "session.diff") {
if (event === undefined || event.type !== "message.updated") {
return undefined;
}

Expand All @@ -30,15 +31,36 @@ function extractDiffTracePayload(
return undefined;
}

const propertiesObj = properties as Record<string, unknown>;
const propertiesObj = properties;

// Access properties.info (the Message object)
const info = propertiesObj.info;
if (typeof info !== "object" || info === null) {
return undefined;
}

const infoObj = info;

// Only capture user messages (filter out assistant, system, etc.)
if (infoObj.role !== "user") {
return undefined;
}

const sessionID =
typeof propertiesObj.sessionID === "string" &&
propertiesObj.sessionID.trim().length > 0
? propertiesObj.sessionID
typeof infoObj.sessionID === "string" &&
infoObj.sessionID.trim().length > 0
? infoObj.sessionID
: "unknown";

const diffEntries = propertiesObj.diff;
const model = infoObj.model;

// Access info.summary?.diffs via explicit checks
const summary = infoObj.summary;
const diffEntries =
typeof summary === "object" && summary !== null
? (summary).diffs
: undefined;

if (!Array.isArray(diffEntries) || diffEntries.length === 0) {
return undefined;
}
Expand All @@ -48,16 +70,10 @@ function extractDiffTracePayload(
if (typeof entry !== "object" || entry === null) {
continue;
}
const entryObj = entry as Record<string, unknown>;
const patch =
typeof entryObj.patch === "string"
? entryObj.patch
: typeof entryObj.diff === "string"
? entryObj.diff
: undefined;
if (patch !== undefined && patch.trim().length > 0) {
patches.push(patch);
}
const entryObj = entry as {patch?:string};
const patch = entryObj.patch || "";

patches.push(patch);
}

if (patches.length === 0) {
Expand All @@ -68,6 +84,7 @@ function extractDiffTracePayload(
sessionID,
diff: patches.join("\n"),
time: Date.now(),
model_id: `${model.providerID}/${model.modelID}`,
};
}

Expand Down
51 changes: 34 additions & 17 deletions config/automated/.opencode/plugins/sce-agent-trace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { Hooks, Plugin } from "@opencode-ai/plugin";

type OpenCodeEvent = Parameters<NonNullable<Hooks["event"]>>[0]["event"];

const REQUIRED_EVENTS = new Set(["session.diff"]);
const REQUIRED_EVENTS = new Set(["message.updated"]);

const ALL_CAPTURED_EVENTS = REQUIRED_EVENTS;

Expand All @@ -15,13 +15,14 @@ type DiffTracePayload = {
sessionID: string;
diff: string;
time: number;
model_id: string;
};

function extractDiffTracePayload(
input: TraceInput,
): DiffTracePayload | undefined {
const event = input.event;
if (event === undefined || event.type !== "session.diff") {
if (event === undefined || event.type !== "message.updated") {
return undefined;
}

Expand All @@ -30,15 +31,36 @@ function extractDiffTracePayload(
return undefined;
}

const propertiesObj = properties as Record<string, unknown>;
const propertiesObj = properties;

// Access properties.info (the Message object)
const info = propertiesObj.info;
if (typeof info !== "object" || info === null) {
return undefined;
}

const infoObj = info;

// Only capture user messages (filter out assistant, system, etc.)
if (infoObj.role !== "user") {
return undefined;
}

const sessionID =
typeof propertiesObj.sessionID === "string" &&
propertiesObj.sessionID.trim().length > 0
? propertiesObj.sessionID
typeof infoObj.sessionID === "string" &&
infoObj.sessionID.trim().length > 0
? infoObj.sessionID
: "unknown";

const diffEntries = propertiesObj.diff;
const model = infoObj.model;

// Access info.summary?.diffs via explicit checks
const summary = infoObj.summary;
const diffEntries =
typeof summary === "object" && summary !== null
? (summary).diffs
: undefined;

if (!Array.isArray(diffEntries) || diffEntries.length === 0) {
return undefined;
}
Expand All @@ -48,16 +70,10 @@ function extractDiffTracePayload(
if (typeof entry !== "object" || entry === null) {
continue;
}
const entryObj = entry as Record<string, unknown>;
const patch =
typeof entryObj.patch === "string"
? entryObj.patch
: typeof entryObj.diff === "string"
? entryObj.diff
: undefined;
if (patch !== undefined && patch.trim().length > 0) {
patches.push(patch);
}
const entryObj = entry as {patch?:string};
const patch = entryObj.patch || "";

patches.push(patch);
}

if (patches.length === 0) {
Expand All @@ -68,6 +84,7 @@ function extractDiffTracePayload(
sessionID,
diff: patches.join("\n"),
time: Date.now(),
model_id: `${model.providerID}/${model.modelID}`,
};
}

Expand Down
Loading