agent-trace 0.2.10 → 0.2.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/agent-trace.cjs +87 -2
  2. package/package.json +1 -1
package/agent-trace.cjs CHANGED
@@ -25077,6 +25077,18 @@ CREATE TABLE IF NOT EXISTS commits (
25077
25077
  );
25078
25078
 
25079
25079
  CREATE INDEX IF NOT EXISTS idx_commits_session ON commits(session_id);
25080
+
25081
+ CREATE TABLE IF NOT EXISTS pull_requests (
25082
+ session_id TEXT NOT NULL,
25083
+ repo TEXT NOT NULL,
25084
+ pr_number INTEGER NOT NULL,
25085
+ state TEXT NOT NULL DEFAULT 'open',
25086
+ url TEXT,
25087
+ merged_at TEXT,
25088
+ PRIMARY KEY (session_id, repo, pr_number)
25089
+ );
25090
+
25091
+ CREATE INDEX IF NOT EXISTS idx_pull_requests_session ON pull_requests(session_id);
25080
25092
  `;
25081
25093
  function toJsonArray(value) {
25082
25094
  return JSON.stringify(value);
@@ -25259,6 +25271,37 @@ var SqliteClient = class {
25259
25271
  });
25260
25272
  transaction(rows);
25261
25273
  }
25274
+ async upsertPullRequests(rows) {
25275
+ if (rows.length === 0) return;
25276
+ const upsert = this.db.prepare(`
25277
+ INSERT INTO pull_requests
25278
+ (session_id, repo, pr_number, state, url, merged_at)
25279
+ VALUES (?, ?, ?, ?, ?, ?)
25280
+ ON CONFLICT(session_id, repo, pr_number) DO UPDATE SET
25281
+ state = excluded.state,
25282
+ url = COALESCE(excluded.url, pull_requests.url),
25283
+ merged_at = COALESCE(excluded.merged_at, pull_requests.merged_at)
25284
+ `);
25285
+ const transaction = this.db.transaction((prRows) => {
25286
+ for (const row of prRows) {
25287
+ upsert.run(
25288
+ row.session_id,
25289
+ row.repo,
25290
+ row.pr_number,
25291
+ row.state,
25292
+ row.url,
25293
+ row.merged_at
25294
+ );
25295
+ }
25296
+ });
25297
+ transaction(rows);
25298
+ }
25299
+ listPullRequestsBySessionId(sessionId) {
25300
+ const rows = this.db.prepare(
25301
+ "SELECT session_id, repo, pr_number, state, url, merged_at FROM pull_requests WHERE session_id = ? ORDER BY pr_number ASC"
25302
+ ).all(sessionId);
25303
+ return rows;
25304
+ }
25262
25305
  listCommitsBySessionId(sessionId) {
25263
25306
  const rows = this.db.prepare(
25264
25307
  "SELECT sha, session_id, prompt_id, message, lines_added, lines_removed, committed_at FROM commits WHERE session_id = ? ORDER BY committed_at ASC"
@@ -25976,6 +26019,19 @@ function toPostgresCommitRow(trace, commit) {
25976
26019
  function toPostgresCommitRows(trace) {
25977
26020
  return trace.git.commits.map((commit) => toPostgresCommitRow(trace, commit));
25978
26021
  }
26022
+ function toPostgresPullRequestRow(trace, pr) {
26023
+ return {
26024
+ session_id: trace.sessionId,
26025
+ repo: pr.repo,
26026
+ pr_number: pr.prNumber,
26027
+ state: pr.state,
26028
+ url: toNullableString(pr.url),
26029
+ merged_at: toNullableString(pr.mergedAt)
26030
+ };
26031
+ }
26032
+ function toPostgresPullRequestRows(trace) {
26033
+ return trace.git.pullRequests.map((pr) => toPostgresPullRequestRow(trace, pr));
26034
+ }
25979
26035
  function dedupeBySessionId(rows) {
25980
26036
  const bySession = /* @__PURE__ */ new Map();
25981
26037
  rows.forEach((row) => {
@@ -25990,6 +26046,13 @@ function dedupeBySha(rows) {
25990
26046
  });
25991
26047
  return [...bySha.values()];
25992
26048
  }
26049
+ function dedupePullRequests(rows) {
26050
+ const byKey = /* @__PURE__ */ new Map();
26051
+ rows.forEach((row) => {
26052
+ byKey.set(`${row.session_id}:${row.repo}:${String(row.pr_number)}`, row);
26053
+ });
26054
+ return [...byKey.values()];
26055
+ }
25993
26056
  var PostgresSessionWriter = class {
25994
26057
  client;
25995
26058
  constructor(client) {
@@ -26007,9 +26070,11 @@ var PostgresSessionWriter = class {
26007
26070
  }
26008
26071
  const sessions = dedupeBySessionId(traces.map(toPostgresSessionRow));
26009
26072
  const commitRows = dedupeBySha(traces.flatMap((trace) => toPostgresCommitRows(trace)));
26073
+ const prRows = dedupePullRequests(traces.flatMap((trace) => toPostgresPullRequestRows(trace)));
26010
26074
  const sessionsPromise = this.client.upsertSessions(sessions);
26011
26075
  const commitsPromise = this.client.upsertCommits(commitRows);
26012
- await Promise.all([sessionsPromise, commitsPromise]);
26076
+ const prsPromise = this.client.upsertPullRequests(prRows);
26077
+ await Promise.all([sessionsPromise, commitsPromise, prsPromise]);
26013
26078
  return {
26014
26079
  writtenSessions: sessions.length,
26015
26080
  writtenCommits: commitRows.length
@@ -28226,6 +28291,7 @@ var InMemoryRuntimeClickHouseClient = class {
28226
28291
  var InMemoryRuntimePostgresClient = class {
28227
28292
  sessionsById = /* @__PURE__ */ new Map();
28228
28293
  commitsBySha = /* @__PURE__ */ new Map();
28294
+ pullRequestsByKey = /* @__PURE__ */ new Map();
28229
28295
  async upsertSessions(rows) {
28230
28296
  rows.forEach((row) => {
28231
28297
  this.sessionsById.set(row.session_id, row);
@@ -28236,12 +28302,20 @@ var InMemoryRuntimePostgresClient = class {
28236
28302
  this.commitsBySha.set(row.sha, row);
28237
28303
  });
28238
28304
  }
28305
+ async upsertPullRequests(rows) {
28306
+ rows.forEach((row) => {
28307
+ this.pullRequestsByKey.set(`${row.session_id}:${row.repo}:${String(row.pr_number)}`, row);
28308
+ });
28309
+ }
28239
28310
  listSessions() {
28240
28311
  return [...this.sessionsById.values()];
28241
28312
  }
28242
28313
  listCommits() {
28243
28314
  return [...this.commitsBySha.values()];
28244
28315
  }
28316
+ listPullRequests() {
28317
+ return [...this.pullRequestsByKey.values()];
28318
+ }
28245
28319
  };
28246
28320
  var InMemoryRuntimeSessionTraceClient = class {
28247
28321
  rows = [];
@@ -28851,10 +28925,21 @@ function hydrateFromSqlite(runtime, sqlite, limit, eventLimit) {
28851
28925
  const extra = commits.filter((c) => !pgShas.has(c.sha));
28852
28926
  commits = [...mapped, ...extra];
28853
28927
  }
28928
+ let pullRequests = trace.git.pullRequests;
28929
+ const pgPrs = sqlite.listPullRequestsBySessionId(row.session_id);
28930
+ if (pgPrs.length > 0) {
28931
+ pullRequests = pgPrs.map((pr) => ({
28932
+ repo: pr.repo,
28933
+ prNumber: pr.pr_number,
28934
+ state: pr.state,
28935
+ ...pr.url !== null ? { url: pr.url } : {},
28936
+ ...pr.merged_at !== null ? { mergedAt: pr.merged_at } : {}
28937
+ }));
28938
+ }
28854
28939
  let hydratedTrace = {
28855
28940
  ...trace,
28856
28941
  timeline,
28857
- git: { ...trace.git, commits }
28942
+ git: { ...trace.git, commits, pullRequests }
28858
28943
  };
28859
28944
  if (hydratedTrace.metrics.totalCostUsd === 0 && (hydratedTrace.metrics.totalInputTokens > 0 || hydratedTrace.metrics.totalOutputTokens > 0) && hydratedTrace.metrics.modelsUsed.length > 0) {
28860
28945
  const model = String(hydratedTrace.metrics.modelsUsed[0]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-trace",
3
- "version": "0.2.10",
3
+ "version": "0.2.11",
4
4
  "description": "Self-hosted observability for AI coding agents. One command, zero config.",
5
5
  "license": "Apache-2.0",
6
6
  "bin": {