@elizaos/plugin-trajectory-logger 2.0.0-alpha.7 → 2.0.0-alpha.9

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.
@@ -10,7 +10,7 @@ var __export = (target, all) => {
10
10
  };
11
11
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
12
12
 
13
- // ../../../node_modules/.bun/drizzle-orm@0.45.1/node_modules/drizzle-orm/entity.js
13
+ // ../../../node_modules/.pnpm/drizzle-orm@0.45.1_@electric-sql+pglite@0.3.15_@neondatabase+serverless@1.0.2_@opentelemetry+_7qzarrdo6qvvshsh3fvwkgjp5i/node_modules/drizzle-orm/entity.js
14
14
  function is(value, type) {
15
15
  if (!value || typeof value !== "object") {
16
16
  return false;
@@ -38,7 +38,7 @@ var init_entity = __esm(() => {
38
38
  hasOwnEntityKind = Symbol.for("drizzle:hasOwnEntityKind");
39
39
  });
40
40
 
41
- // ../../../node_modules/.bun/drizzle-orm@0.45.1/node_modules/drizzle-orm/column.js
41
+ // ../../../node_modules/.pnpm/drizzle-orm@0.45.1_@electric-sql+pglite@0.3.15_@neondatabase+serverless@1.0.2_@opentelemetry+_7qzarrdo6qvvshsh3fvwkgjp5i/node_modules/drizzle-orm/column.js
42
42
  var Column;
43
43
  var init_column = __esm(() => {
44
44
  init_entity();
@@ -92,7 +92,7 @@ var init_column = __esm(() => {
92
92
  };
93
93
  });
94
94
 
95
- // ../../../node_modules/.bun/drizzle-orm@0.45.1/node_modules/drizzle-orm/column-builder.js
95
+ // ../../../node_modules/.pnpm/drizzle-orm@0.45.1_@electric-sql+pglite@0.3.15_@neondatabase+serverless@1.0.2_@opentelemetry+_7qzarrdo6qvvshsh3fvwkgjp5i/node_modules/drizzle-orm/column-builder.js
96
96
  var ColumnBuilder;
97
97
  var init_column_builder = __esm(() => {
98
98
  init_entity();
@@ -152,19 +152,19 @@ var init_column_builder = __esm(() => {
152
152
  };
153
153
  });
154
154
 
155
- // ../../../node_modules/.bun/drizzle-orm@0.45.1/node_modules/drizzle-orm/table.utils.js
155
+ // ../../../node_modules/.pnpm/drizzle-orm@0.45.1_@electric-sql+pglite@0.3.15_@neondatabase+serverless@1.0.2_@opentelemetry+_7qzarrdo6qvvshsh3fvwkgjp5i/node_modules/drizzle-orm/table.utils.js
156
156
  var TableName;
157
157
  var init_table_utils = __esm(() => {
158
158
  TableName = Symbol.for("drizzle:Name");
159
159
  });
160
160
 
161
- // ../../../node_modules/.bun/drizzle-orm@0.45.1/node_modules/drizzle-orm/tracing-utils.js
161
+ // ../../../node_modules/.pnpm/drizzle-orm@0.45.1_@electric-sql+pglite@0.3.15_@neondatabase+serverless@1.0.2_@opentelemetry+_7qzarrdo6qvvshsh3fvwkgjp5i/node_modules/drizzle-orm/tracing-utils.js
162
162
  function iife(fn, ...args) {
163
163
  return fn(...args);
164
164
  }
165
165
  var init_tracing_utils = () => {};
166
166
 
167
- // ../../../node_modules/.bun/drizzle-orm@0.45.1/node_modules/drizzle-orm/pg-core/unique-constraint.js
167
+ // ../../../node_modules/.pnpm/drizzle-orm@0.45.1_@electric-sql+pglite@0.3.15_@neondatabase+serverless@1.0.2_@opentelemetry+_7qzarrdo6qvvshsh3fvwkgjp5i/node_modules/drizzle-orm/pg-core/unique-constraint.js
168
168
  function uniqueKeyName(table, columns) {
169
169
  return `${table[TableName]}_${columns.join("_")}_unique`;
170
170
  }
@@ -172,7 +172,7 @@ var init_unique_constraint = __esm(() => {
172
172
  init_table_utils();
173
173
  });
174
174
 
175
- // ../../../node_modules/.bun/drizzle-orm@0.45.1/node_modules/drizzle-orm/pg-core/columns/common.js
175
+ // ../../../node_modules/.pnpm/drizzle-orm@0.45.1_@electric-sql+pglite@0.3.15_@neondatabase+serverless@1.0.2_@opentelemetry+_7qzarrdo6qvvshsh3fvwkgjp5i/node_modules/drizzle-orm/pg-core/columns/common.js
176
176
  var PgColumn, ExtraConfigColumn;
177
177
  var init_common = __esm(() => {
178
178
  init_column();
@@ -226,7 +226,7 @@ var init_common = __esm(() => {
226
226
  };
227
227
  });
228
228
 
229
- // ../../../node_modules/.bun/drizzle-orm@0.45.1/node_modules/drizzle-orm/pg-core/columns/enum.js
229
+ // ../../../node_modules/.pnpm/drizzle-orm@0.45.1_@electric-sql+pglite@0.3.15_@neondatabase+serverless@1.0.2_@opentelemetry+_7qzarrdo6qvvshsh3fvwkgjp5i/node_modules/drizzle-orm/pg-core/columns/enum.js
230
230
  function isPgEnum(obj) {
231
231
  return !!obj && typeof obj === "function" && isPgEnumSym in obj && obj[isPgEnumSym] === true;
232
232
  }
@@ -261,7 +261,7 @@ var init_enum = __esm(() => {
261
261
  };
262
262
  });
263
263
 
264
- // ../../../node_modules/.bun/drizzle-orm@0.45.1/node_modules/drizzle-orm/subquery.js
264
+ // ../../../node_modules/.pnpm/drizzle-orm@0.45.1_@electric-sql+pglite@0.3.15_@neondatabase+serverless@1.0.2_@opentelemetry+_7qzarrdo6qvvshsh3fvwkgjp5i/node_modules/drizzle-orm/subquery.js
265
265
  var Subquery, WithSubquery;
266
266
  var init_subquery = __esm(() => {
267
267
  init_entity();
@@ -283,11 +283,11 @@ var init_subquery = __esm(() => {
283
283
  };
284
284
  });
285
285
 
286
- // ../../../node_modules/.bun/drizzle-orm@0.45.1/node_modules/drizzle-orm/version.js
286
+ // ../../../node_modules/.pnpm/drizzle-orm@0.45.1_@electric-sql+pglite@0.3.15_@neondatabase+serverless@1.0.2_@opentelemetry+_7qzarrdo6qvvshsh3fvwkgjp5i/node_modules/drizzle-orm/version.js
287
287
  var version = "0.45.1";
288
288
  var init_version = () => {};
289
289
 
290
- // ../../../node_modules/.bun/drizzle-orm@0.45.1/node_modules/drizzle-orm/tracing.js
290
+ // ../../../node_modules/.pnpm/drizzle-orm@0.45.1_@electric-sql+pglite@0.3.15_@neondatabase+serverless@1.0.2_@opentelemetry+_7qzarrdo6qvvshsh3fvwkgjp5i/node_modules/drizzle-orm/tracing.js
291
291
  var otel, rawTracer, tracer;
292
292
  var init_tracing = __esm(() => {
293
293
  init_tracing_utils();
@@ -317,13 +317,13 @@ var init_tracing = __esm(() => {
317
317
  };
318
318
  });
319
319
 
320
- // ../../../node_modules/.bun/drizzle-orm@0.45.1/node_modules/drizzle-orm/view-common.js
320
+ // ../../../node_modules/.pnpm/drizzle-orm@0.45.1_@electric-sql+pglite@0.3.15_@neondatabase+serverless@1.0.2_@opentelemetry+_7qzarrdo6qvvshsh3fvwkgjp5i/node_modules/drizzle-orm/view-common.js
321
321
  var ViewBaseConfig;
322
322
  var init_view_common = __esm(() => {
323
323
  ViewBaseConfig = Symbol.for("drizzle:ViewBaseConfig");
324
324
  });
325
325
 
326
- // ../../../node_modules/.bun/drizzle-orm@0.45.1/node_modules/drizzle-orm/table.js
326
+ // ../../../node_modules/.pnpm/drizzle-orm@0.45.1_@electric-sql+pglite@0.3.15_@neondatabase+serverless@1.0.2_@opentelemetry+_7qzarrdo6qvvshsh3fvwkgjp5i/node_modules/drizzle-orm/table.js
327
327
  function isTable(table) {
328
328
  return typeof table === "object" && table !== null && IsDrizzleTable in table;
329
329
  }
@@ -374,7 +374,7 @@ var init_table = __esm(() => {
374
374
  };
375
375
  });
376
376
 
377
- // ../../../node_modules/.bun/drizzle-orm@0.45.1/node_modules/drizzle-orm/sql/sql.js
377
+ // ../../../node_modules/.pnpm/drizzle-orm@0.45.1_@electric-sql+pglite@0.3.15_@neondatabase+serverless@1.0.2_@opentelemetry+_7qzarrdo6qvvshsh3fvwkgjp5i/node_modules/drizzle-orm/sql/sql.js
378
378
  function isSQLWrapper(value) {
379
379
  return value !== null && value !== undefined && typeof value.getSQL === "function";
380
380
  }
@@ -776,7 +776,7 @@ var init_sql = __esm(() => {
776
776
  };
777
777
  });
778
778
 
779
- // ../../../node_modules/.bun/drizzle-orm@0.45.1/node_modules/drizzle-orm/alias.js
779
+ // ../../../node_modules/.pnpm/drizzle-orm@0.45.1_@electric-sql+pglite@0.3.15_@neondatabase+serverless@1.0.2_@opentelemetry+_7qzarrdo6qvvshsh3fvwkgjp5i/node_modules/drizzle-orm/alias.js
780
780
  function aliasedTable(table, tableAlias) {
781
781
  return new Proxy(table, new TableAliasProxyHandler(tableAlias, false));
782
782
  }
@@ -877,7 +877,7 @@ var init_alias = __esm(() => {
877
877
  };
878
878
  });
879
879
 
880
- // ../../../node_modules/.bun/drizzle-orm@0.45.1/node_modules/drizzle-orm/errors.js
880
+ // ../../../node_modules/.pnpm/drizzle-orm@0.45.1_@electric-sql+pglite@0.3.15_@neondatabase+serverless@1.0.2_@opentelemetry+_7qzarrdo6qvvshsh3fvwkgjp5i/node_modules/drizzle-orm/errors.js
881
881
  var DrizzleError, DrizzleQueryError, TransactionRollbackError;
882
882
  var init_errors = __esm(() => {
883
883
  init_entity();
@@ -909,7 +909,7 @@ params: ${params}`);
909
909
  };
910
910
  });
911
911
 
912
- // ../../../node_modules/.bun/drizzle-orm@0.45.1/node_modules/drizzle-orm/logger.js
912
+ // ../../../node_modules/.pnpm/drizzle-orm@0.45.1_@electric-sql+pglite@0.3.15_@neondatabase+serverless@1.0.2_@opentelemetry+_7qzarrdo6qvvshsh3fvwkgjp5i/node_modules/drizzle-orm/logger.js
913
913
  var ConsoleLogWriter, DefaultLogger, NoopLogger;
914
914
  var init_logger = __esm(() => {
915
915
  init_entity();
@@ -943,7 +943,7 @@ var init_logger = __esm(() => {
943
943
  };
944
944
  });
945
945
 
946
- // ../../../node_modules/.bun/drizzle-orm@0.45.1/node_modules/drizzle-orm/query-promise.js
946
+ // ../../../node_modules/.pnpm/drizzle-orm@0.45.1_@electric-sql+pglite@0.3.15_@neondatabase+serverless@1.0.2_@opentelemetry+_7qzarrdo6qvvshsh3fvwkgjp5i/node_modules/drizzle-orm/query-promise.js
947
947
  var QueryPromise;
948
948
  var init_query_promise = __esm(() => {
949
949
  init_entity();
@@ -968,7 +968,7 @@ var init_query_promise = __esm(() => {
968
968
  };
969
969
  });
970
970
 
971
- // ../../../node_modules/.bun/drizzle-orm@0.45.1/node_modules/drizzle-orm/utils.js
971
+ // ../../../node_modules/.pnpm/drizzle-orm@0.45.1_@electric-sql+pglite@0.3.15_@neondatabase+serverless@1.0.2_@opentelemetry+_7qzarrdo6qvvshsh3fvwkgjp5i/node_modules/drizzle-orm/utils.js
972
972
  function mapResultRow(columns, row, joinsNotNullableMap) {
973
973
  const nullifyMap = {};
974
974
  const result = columns.reduce((result2, { path, field }, columnIndex) => {
@@ -1134,7 +1134,7 @@ var init_utils = __esm(() => {
1134
1134
  textDecoder = typeof TextDecoder === "undefined" ? null : new TextDecoder;
1135
1135
  });
1136
1136
 
1137
- // ../../../node_modules/.bun/drizzle-orm@0.45.1/node_modules/drizzle-orm/pg-core/table.js
1137
+ // ../../../node_modules/.pnpm/drizzle-orm@0.45.1_@electric-sql+pglite@0.3.15_@neondatabase+serverless@1.0.2_@opentelemetry+_7qzarrdo6qvvshsh3fvwkgjp5i/node_modules/drizzle-orm/pg-core/table.js
1138
1138
  var InlineForeignKeys, EnableRLS, PgTable;
1139
1139
  var init_table2 = __esm(() => {
1140
1140
  init_entity();
@@ -1154,7 +1154,7 @@ var init_table2 = __esm(() => {
1154
1154
  };
1155
1155
  });
1156
1156
 
1157
- // ../../../node_modules/.bun/drizzle-orm@0.45.1/node_modules/drizzle-orm/pg-core/primary-keys.js
1157
+ // ../../../node_modules/.pnpm/drizzle-orm@0.45.1_@electric-sql+pglite@0.3.15_@neondatabase+serverless@1.0.2_@opentelemetry+_7qzarrdo6qvvshsh3fvwkgjp5i/node_modules/drizzle-orm/pg-core/primary-keys.js
1158
1158
  var PrimaryKeyBuilder, PrimaryKey;
1159
1159
  var init_primary_keys = __esm(() => {
1160
1160
  init_entity();
@@ -1186,7 +1186,7 @@ var init_primary_keys = __esm(() => {
1186
1186
  };
1187
1187
  });
1188
1188
 
1189
- // ../../../node_modules/.bun/drizzle-orm@0.45.1/node_modules/drizzle-orm/sql/expressions/conditions.js
1189
+ // ../../../node_modules/.pnpm/drizzle-orm@0.45.1_@electric-sql+pglite@0.3.15_@neondatabase+serverless@1.0.2_@opentelemetry+_7qzarrdo6qvvshsh3fvwkgjp5i/node_modules/drizzle-orm/sql/expressions/conditions.js
1190
1190
  function bindIfParam(value, column) {
1191
1191
  if (isDriverValueEncoder(column) && !isSQLWrapper(value) && !is(value, Param) && !is(value, Placeholder) && !is(value, Column) && !is(value, Table) && !is(value, View)) {
1192
1192
  return new Param(value, column);
@@ -1322,7 +1322,7 @@ var init_conditions = __esm(() => {
1322
1322
  init_sql();
1323
1323
  });
1324
1324
 
1325
- // ../../../node_modules/.bun/drizzle-orm@0.45.1/node_modules/drizzle-orm/sql/expressions/select.js
1325
+ // ../../../node_modules/.pnpm/drizzle-orm@0.45.1_@electric-sql+pglite@0.3.15_@neondatabase+serverless@1.0.2_@opentelemetry+_7qzarrdo6qvvshsh3fvwkgjp5i/node_modules/drizzle-orm/sql/expressions/select.js
1326
1326
  function asc(column) {
1327
1327
  return sql`${column} asc`;
1328
1328
  }
@@ -1333,13 +1333,13 @@ var init_select = __esm(() => {
1333
1333
  init_sql();
1334
1334
  });
1335
1335
 
1336
- // ../../../node_modules/.bun/drizzle-orm@0.45.1/node_modules/drizzle-orm/sql/expressions/index.js
1336
+ // ../../../node_modules/.pnpm/drizzle-orm@0.45.1_@electric-sql+pglite@0.3.15_@neondatabase+serverless@1.0.2_@opentelemetry+_7qzarrdo6qvvshsh3fvwkgjp5i/node_modules/drizzle-orm/sql/expressions/index.js
1337
1337
  var init_expressions = __esm(() => {
1338
1338
  init_conditions();
1339
1339
  init_select();
1340
1340
  });
1341
1341
 
1342
- // ../../../node_modules/.bun/drizzle-orm@0.45.1/node_modules/drizzle-orm/relations.js
1342
+ // ../../../node_modules/.pnpm/drizzle-orm@0.45.1_@electric-sql+pglite@0.3.15_@neondatabase+serverless@1.0.2_@opentelemetry+_7qzarrdo6qvvshsh3fvwkgjp5i/node_modules/drizzle-orm/relations.js
1343
1343
  function getOperators() {
1344
1344
  return {
1345
1345
  and,
@@ -1571,7 +1571,7 @@ var init_relations = __esm(() => {
1571
1571
  };
1572
1572
  });
1573
1573
 
1574
- // ../../../node_modules/.bun/drizzle-orm@0.45.1/node_modules/drizzle-orm/sql/functions/aggregate.js
1574
+ // ../../../node_modules/.pnpm/drizzle-orm@0.45.1_@electric-sql+pglite@0.3.15_@neondatabase+serverless@1.0.2_@opentelemetry+_7qzarrdo6qvvshsh3fvwkgjp5i/node_modules/drizzle-orm/sql/functions/aggregate.js
1575
1575
  function count(expression) {
1576
1576
  return sql`count(${expression || sql.raw("*")})`.mapWith(Number);
1577
1577
  }
@@ -1602,7 +1602,7 @@ var init_aggregate = __esm(() => {
1602
1602
  init_sql();
1603
1603
  });
1604
1604
 
1605
- // ../../../node_modules/.bun/drizzle-orm@0.45.1/node_modules/drizzle-orm/sql/functions/vector.js
1605
+ // ../../../node_modules/.pnpm/drizzle-orm@0.45.1_@electric-sql+pglite@0.3.15_@neondatabase+serverless@1.0.2_@opentelemetry+_7qzarrdo6qvvshsh3fvwkgjp5i/node_modules/drizzle-orm/sql/functions/vector.js
1606
1606
  function toSql(value) {
1607
1607
  return JSON.stringify(value);
1608
1608
  }
@@ -1646,20 +1646,20 @@ var init_vector = __esm(() => {
1646
1646
  init_sql();
1647
1647
  });
1648
1648
 
1649
- // ../../../node_modules/.bun/drizzle-orm@0.45.1/node_modules/drizzle-orm/sql/functions/index.js
1649
+ // ../../../node_modules/.pnpm/drizzle-orm@0.45.1_@electric-sql+pglite@0.3.15_@neondatabase+serverless@1.0.2_@opentelemetry+_7qzarrdo6qvvshsh3fvwkgjp5i/node_modules/drizzle-orm/sql/functions/index.js
1650
1650
  var init_functions = __esm(() => {
1651
1651
  init_aggregate();
1652
1652
  init_vector();
1653
1653
  });
1654
1654
 
1655
- // ../../../node_modules/.bun/drizzle-orm@0.45.1/node_modules/drizzle-orm/sql/index.js
1655
+ // ../../../node_modules/.pnpm/drizzle-orm@0.45.1_@electric-sql+pglite@0.3.15_@neondatabase+serverless@1.0.2_@opentelemetry+_7qzarrdo6qvvshsh3fvwkgjp5i/node_modules/drizzle-orm/sql/index.js
1656
1656
  var init_sql2 = __esm(() => {
1657
1657
  init_expressions();
1658
1658
  init_functions();
1659
1659
  init_sql();
1660
1660
  });
1661
1661
 
1662
- // ../../../node_modules/.bun/drizzle-orm@0.45.1/node_modules/drizzle-orm/index.js
1662
+ // ../../../node_modules/.pnpm/drizzle-orm@0.45.1_@electric-sql+pglite@0.3.15_@neondatabase+serverless@1.0.2_@opentelemetry+_7qzarrdo6qvvshsh3fvwkgjp5i/node_modules/drizzle-orm/index.js
1663
1663
  var exports_drizzle_orm = {};
1664
1664
  __export(exports_drizzle_orm, {
1665
1665
  textDecoder: () => textDecoder,
@@ -1797,6 +1797,12 @@ var init_drizzle_orm = __esm(() => {
1797
1797
  init_view_common();
1798
1798
  });
1799
1799
 
1800
+ // index.ts
1801
+ import {
1802
+ createUniqueUuid
1803
+ } from "@elizaos/core";
1804
+ import crypto from "node:crypto";
1805
+
1800
1806
  // TrajectoryLoggerService.ts
1801
1807
  import { logger as logger2, Service } from "@elizaos/core";
1802
1808
  import { v4 as uuidv4 } from "uuid";
@@ -1851,6 +1857,9 @@ function sqlLiteral(v) {
1851
1857
 
1852
1858
  class TrajectoryLoggerService extends Service {
1853
1859
  static serviceType = "trajectory_logger";
1860
+ get serviceType() {
1861
+ return TrajectoryLoggerService.serviceType;
1862
+ }
1854
1863
  capabilityDescription = "Captures and persists LLM calls, provider accesses, and full trajectories for debugging, analysis, and RL training";
1855
1864
  enabled = true;
1856
1865
  initialized = false;
@@ -1858,7 +1867,7 @@ class TrajectoryLoggerService extends Service {
1858
1867
  stepToTrajectory = new Map;
1859
1868
  writeQueues = new Map;
1860
1869
  static async start(runtime) {
1861
- const service = new TrajectoryLoggerService(runtime);
1870
+ const service = new this(runtime);
1862
1871
  await service.initialize();
1863
1872
  return service;
1864
1873
  }
@@ -1897,6 +1906,7 @@ class TrajectoryLoggerService extends Service {
1897
1906
  return;
1898
1907
  }
1899
1908
  await this.ensureTablesExist();
1909
+ await this.backfillTrajectoriesMissingLlmCalls();
1900
1910
  this.initialized = true;
1901
1911
  logger2.info("[trajectory-logger] Trajectory logger service initialized");
1902
1912
  }
@@ -2041,6 +2051,56 @@ class TrajectoryLoggerService extends Service {
2041
2051
  await this.executeRawSql(`CREATE INDEX IF NOT EXISTS idx_trajectory_step_index_trajectory_id ON trajectory_step_index(trajectory_id)`);
2042
2052
  await this.executeRawSql(`CREATE INDEX IF NOT EXISTS idx_trajectory_step_index_is_active ON trajectory_step_index(is_active)`);
2043
2053
  }
2054
+ normalizeTrajectoryStatus(value) {
2055
+ switch (value) {
2056
+ case "active":
2057
+ case "completed":
2058
+ case "error":
2059
+ case "timeout":
2060
+ case "terminated":
2061
+ return value;
2062
+ default:
2063
+ return "completed";
2064
+ }
2065
+ }
2066
+ async backfillTrajectoriesMissingLlmCalls() {
2067
+ const maxRows = 2000;
2068
+ let fixed = 0;
2069
+ try {
2070
+ const rows = await this.executeRawSql(`
2071
+ SELECT id, status
2072
+ FROM trajectories
2073
+ WHERE COALESCE(llm_call_count, 0) = 0
2074
+ AND status <> 'active'
2075
+ ORDER BY created_at ASC
2076
+ LIMIT ${maxRows}
2077
+ `);
2078
+ for (const row of rows.rows) {
2079
+ const trajectoryId = asString(pickCell(row, "id"));
2080
+ if (!trajectoryId)
2081
+ continue;
2082
+ const status = this.normalizeTrajectoryStatus(asString(pickCell(row, "status")));
2083
+ await this.withTrajectoryWriteLock(trajectoryId, async () => {
2084
+ const trajectory = await this.getTrajectoryById(trajectoryId);
2085
+ if (!trajectory)
2086
+ return;
2087
+ const inserted = this.ensureAtLeastOneLlmCall(trajectory, "backfill");
2088
+ if (!inserted)
2089
+ return;
2090
+ await this.persistTrajectory(trajectoryId, trajectory, status);
2091
+ fixed += 1;
2092
+ });
2093
+ }
2094
+ if (fixed > 0) {
2095
+ logger2.info(`[trajectory-logger] Backfilled ${fixed} completed trajectories with synthetic LLM calls`);
2096
+ }
2097
+ if (rows.rows.length >= maxRows) {
2098
+ logger2.warn(`[trajectory-logger] Backfill hit safety cap (${maxRows}); remaining older trajectories will be fixed lazily when touched`);
2099
+ }
2100
+ } catch (err) {
2101
+ logger2.warn(`[trajectory-logger] Failed to backfill trajectories missing LLM calls (non-fatal): ${err instanceof Error ? err.message : String(err)}`);
2102
+ }
2103
+ }
2044
2104
  normalizePurpose(value) {
2045
2105
  switch (value) {
2046
2106
  case "action":
@@ -2087,15 +2147,57 @@ class TrajectoryLoggerService extends Service {
2087
2147
  done: false
2088
2148
  };
2089
2149
  }
2150
+ ensureAtLeastOneLlmCall(trajectory, source) {
2151
+ if (this.computeTotals(trajectory.steps).llmCallCount > 0) {
2152
+ return false;
2153
+ }
2154
+ const timestamp = Date.now();
2155
+ let step = trajectory.steps[trajectory.steps.length - 1];
2156
+ if (!step) {
2157
+ step = this.createStep(uuidv4(), 0, this.defaultEnvironmentState(timestamp));
2158
+ step.done = true;
2159
+ trajectory.steps.push(step);
2160
+ }
2161
+ if (!Array.isArray(step.llmCalls)) {
2162
+ step.llmCalls = [];
2163
+ }
2164
+ const syntheticCall = {
2165
+ callId: uuidv4(),
2166
+ timestamp,
2167
+ model: "milady/synthetic-trajectory-fallback",
2168
+ systemPrompt: "[synthetic] inserted by trajectory logger because no LLM calls were captured",
2169
+ userPrompt: "[synthetic] this trajectory completed without recorded model activity",
2170
+ response: "[synthetic] placeholder call inserted to enforce minimum llm_call_count=1",
2171
+ temperature: 0,
2172
+ maxTokens: 0,
2173
+ promptTokens: 0,
2174
+ completionTokens: 0,
2175
+ latencyMs: 0,
2176
+ purpose: "other",
2177
+ actionType: "TRAJECTORY_FALLBACK"
2178
+ };
2179
+ step.llmCalls.push(syntheticCall);
2180
+ if (!step.metadata)
2181
+ step.metadata = {};
2182
+ step.metadata.syntheticLlmCall = true;
2183
+ step.metadata.syntheticLlmCallSource = source;
2184
+ trajectory.metadata.syntheticLlmCall = true;
2185
+ trajectory.metadata.syntheticLlmCallSource = source;
2186
+ const existingFallbackCount = trajectory.metrics.syntheticLlmFallbackCount;
2187
+ trajectory.metrics.syntheticLlmFallbackCount = typeof existingFallbackCount === "number" && Number.isFinite(existingFallbackCount) ? existingFallbackCount + 1 : 1;
2188
+ return true;
2189
+ }
2090
2190
  computeTotals(steps) {
2091
2191
  let llmCallCount = 0;
2092
2192
  let providerAccessCount = 0;
2093
2193
  let totalPromptTokens = 0;
2094
2194
  let totalCompletionTokens = 0;
2095
2195
  for (const step of steps) {
2096
- llmCallCount += step.llmCalls.length;
2097
- providerAccessCount += step.providerAccesses.length;
2098
- for (const call of step.llmCalls) {
2196
+ const llmCalls = Array.isArray(step.llmCalls) ? step.llmCalls : [];
2197
+ const providerAccesses = Array.isArray(step.providerAccesses) ? step.providerAccesses : [];
2198
+ llmCallCount += llmCalls.length;
2199
+ providerAccessCount += providerAccesses.length;
2200
+ for (const call of llmCalls) {
2099
2201
  totalPromptTokens += call.promptTokens ?? 0;
2100
2202
  totalCompletionTokens += call.completionTokens ?? 0;
2101
2203
  }
@@ -2190,6 +2292,9 @@ class TrajectoryLoggerService extends Service {
2190
2292
  return row ? asString(pickCell(row, "step_id")) : null;
2191
2293
  }
2192
2294
  async persistTrajectory(trajectoryId, trajectory, status = "active") {
2295
+ if (status !== "active") {
2296
+ this.ensureAtLeastOneLlmCall(trajectory, "finalize");
2297
+ }
2193
2298
  const totals = this.computeTotals(trajectory.steps);
2194
2299
  const isFinalStatus = status !== "active";
2195
2300
  const persistedEndTime = isFinalStatus ? trajectory.endTime : null;
@@ -2238,8 +2343,13 @@ class TrajectoryLoggerService extends Service {
2238
2343
  }
2239
2344
  async ensureStepExists(trajectory, stepId) {
2240
2345
  let step = trajectory.steps.find((entry) => entry.stepId === stepId);
2241
- if (step)
2346
+ if (step) {
2347
+ if (!Array.isArray(step.llmCalls))
2348
+ step.llmCalls = [];
2349
+ if (!Array.isArray(step.providerAccesses))
2350
+ step.providerAccesses = [];
2242
2351
  return step;
2352
+ }
2243
2353
  const index = await this.getStepIndex(stepId);
2244
2354
  const stepNumber = index?.stepNumber ?? trajectory.steps.length;
2245
2355
  step = this.createStep(stepId, stepNumber, this.defaultEnvironmentState());
@@ -2589,23 +2699,28 @@ class TrajectoryLoggerService extends Service {
2589
2699
  ORDER BY created_at DESC
2590
2700
  LIMIT ${limit} OFFSET ${offset}
2591
2701
  `);
2592
- const trajectories = rowsResult.rows.map((row) => ({
2593
- id: asString(pickCell(row, "id")) ?? "",
2594
- agentId: asString(pickCell(row, "agent_id")) ?? "",
2595
- source: asString(pickCell(row, "source")) ?? "chat",
2596
- status: asString(pickCell(row, "status")) ?? "completed",
2597
- startTime: asNumber(pickCell(row, "start_time")) ?? 0,
2598
- endTime: asNumber(pickCell(row, "end_time")),
2599
- durationMs: asNumber(pickCell(row, "duration_ms")),
2600
- stepCount: asNumber(pickCell(row, "step_count")) ?? 0,
2601
- llmCallCount: asNumber(pickCell(row, "llm_call_count")) ?? 0,
2602
- totalPromptTokens: asNumber(pickCell(row, "total_prompt_tokens")) ?? 0,
2603
- totalCompletionTokens: asNumber(pickCell(row, "total_completion_tokens")) ?? 0,
2604
- totalReward: asNumber(pickCell(row, "total_reward")) ?? 0,
2605
- scenarioId: asString(pickCell(row, "scenario_id")),
2606
- batchId: asString(pickCell(row, "batch_id")),
2607
- createdAt: asIsoString(pickCell(row, "created_at"))
2608
- }));
2702
+ const trajectories = rowsResult.rows.map((row) => {
2703
+ const status = asString(pickCell(row, "status")) ?? "completed";
2704
+ const rawLlmCallCount = asNumber(pickCell(row, "llm_call_count")) ?? 0;
2705
+ const llmCallCount = status === "active" ? rawLlmCallCount : Math.max(1, rawLlmCallCount);
2706
+ return {
2707
+ id: asString(pickCell(row, "id")) ?? "",
2708
+ agentId: asString(pickCell(row, "agent_id")) ?? "",
2709
+ source: asString(pickCell(row, "source")) ?? "chat",
2710
+ status,
2711
+ startTime: asNumber(pickCell(row, "start_time")) ?? 0,
2712
+ endTime: asNumber(pickCell(row, "end_time")),
2713
+ durationMs: asNumber(pickCell(row, "duration_ms")),
2714
+ stepCount: asNumber(pickCell(row, "step_count")) ?? 0,
2715
+ llmCallCount,
2716
+ totalPromptTokens: asNumber(pickCell(row, "total_prompt_tokens")) ?? 0,
2717
+ totalCompletionTokens: asNumber(pickCell(row, "total_completion_tokens")) ?? 0,
2718
+ totalReward: asNumber(pickCell(row, "total_reward")) ?? 0,
2719
+ scenarioId: asString(pickCell(row, "scenario_id")),
2720
+ batchId: asString(pickCell(row, "batch_id")),
2721
+ createdAt: asIsoString(pickCell(row, "created_at"))
2722
+ };
2723
+ });
2609
2724
  return { trajectories, total, offset, limit };
2610
2725
  }
2611
2726
  async getTrajectoryDetail(trajectoryId) {
@@ -2617,7 +2732,17 @@ class TrajectoryLoggerService extends Service {
2617
2732
  if (result.rows.length === 0)
2618
2733
  return null;
2619
2734
  const row = result.rows[0];
2620
- return this.rowToTrajectory(row);
2735
+ const trajectory = this.rowToTrajectory(row);
2736
+ const status = this.normalizeTrajectoryStatus(asString(pickCell(row, "status")));
2737
+ if (status !== "active") {
2738
+ const inserted = this.ensureAtLeastOneLlmCall(trajectory, "backfill");
2739
+ if (inserted) {
2740
+ await this.withTrajectoryWriteLock(trajectoryId, async () => {
2741
+ await this.persistTrajectory(trajectoryId, trajectory, status);
2742
+ });
2743
+ }
2744
+ }
2745
+ return trajectory;
2621
2746
  }
2622
2747
  async getStats() {
2623
2748
  const runtime = this.runtime;
@@ -2716,6 +2841,113 @@ class TrajectoryLoggerService extends Service {
2716
2841
  await this.executeRawSql(`DELETE FROM trajectories`);
2717
2842
  return count2;
2718
2843
  }
2844
+ sanitizeZipFolderName(value) {
2845
+ const sanitized = value.trim().replace(/[^a-zA-Z0-9._-]+/g, "_").replace(/^_+|_+$/g, "");
2846
+ return sanitized || "trajectory";
2847
+ }
2848
+ redactTrajectoryPrompts(trajectory) {
2849
+ return {
2850
+ ...trajectory,
2851
+ steps: trajectory.steps.map((step) => ({
2852
+ ...step,
2853
+ llmCalls: step.llmCalls.map((call) => ({
2854
+ ...call,
2855
+ systemPrompt: "[redacted]",
2856
+ userPrompt: "[redacted]",
2857
+ response: "[redacted]"
2858
+ }))
2859
+ }))
2860
+ };
2861
+ }
2862
+ buildZipSummary(trajectory) {
2863
+ const finalStatus = trajectory.metrics?.finalStatus ?? "completed";
2864
+ const normalizedEndTime = typeof trajectory.endTime === "number" && trajectory.endTime > 0 ? trajectory.endTime : null;
2865
+ const status = finalStatus === "timeout" || finalStatus === "terminated" || finalStatus === "error" ? "error" : finalStatus === "completed" ? "completed" : normalizedEndTime ? "completed" : "active";
2866
+ let llmCallCount = 0;
2867
+ let providerAccessCount = 0;
2868
+ let totalPromptTokens = 0;
2869
+ let totalCompletionTokens = 0;
2870
+ for (const step of trajectory.steps) {
2871
+ providerAccessCount += step.providerAccesses.length;
2872
+ llmCallCount += step.llmCalls.length;
2873
+ for (const call of step.llmCalls) {
2874
+ totalPromptTokens += call.promptTokens ?? 0;
2875
+ totalCompletionTokens += call.completionTokens ?? 0;
2876
+ }
2877
+ }
2878
+ const metadata = trajectory.metadata ?? {};
2879
+ const asNullableString = (value) => typeof value === "string" ? value : null;
2880
+ const source = typeof metadata.source === "string" ? metadata.source : "chat";
2881
+ const normalizedDurationMs = status === "active" ? null : typeof trajectory.durationMs === "number" ? trajectory.durationMs : null;
2882
+ const updatedAtMs = normalizedEndTime ?? (trajectory.startTime || Date.now());
2883
+ return {
2884
+ id: trajectory.trajectoryId,
2885
+ agentId: trajectory.agentId,
2886
+ roomId: asNullableString(metadata.roomId),
2887
+ entityId: asNullableString(metadata.entityId),
2888
+ conversationId: asNullableString(metadata.conversationId),
2889
+ source,
2890
+ status,
2891
+ startTime: trajectory.startTime,
2892
+ endTime: normalizedEndTime,
2893
+ durationMs: normalizedDurationMs,
2894
+ llmCallCount,
2895
+ providerAccessCount,
2896
+ totalPromptTokens,
2897
+ totalCompletionTokens,
2898
+ metadata,
2899
+ createdAt: new Date(trajectory.startTime).toISOString(),
2900
+ updatedAt: new Date(updatedAtMs).toISOString()
2901
+ };
2902
+ }
2903
+ async exportTrajectoriesZip(options = {}) {
2904
+ let targetIds = Array.isArray(options.trajectoryIds) ? options.trajectoryIds.filter((id) => typeof id === "string" && id.trim().length > 0) : [];
2905
+ if (targetIds.length === 0) {
2906
+ const list = await this.listTrajectories({
2907
+ limit: 500,
2908
+ startDate: options.startDate,
2909
+ endDate: options.endDate,
2910
+ scenarioId: options.scenarioId,
2911
+ batchId: options.batchId
2912
+ });
2913
+ targetIds = list.trajectories.map((trajectory) => trajectory.id);
2914
+ }
2915
+ const entries = [];
2916
+ const manifestRows = [];
2917
+ for (const trajectoryId of targetIds) {
2918
+ const detail = await this.getTrajectoryDetail(trajectoryId);
2919
+ if (!detail)
2920
+ continue;
2921
+ const exportTrajectory = options.includePrompts === false ? this.redactTrajectoryPrompts(detail) : detail;
2922
+ const summary = this.buildZipSummary(exportTrajectory);
2923
+ const folderName = this.sanitizeZipFolderName(trajectoryId);
2924
+ entries.push({
2925
+ name: `${folderName}/trajectory.json`,
2926
+ data: JSON.stringify(exportTrajectory, null, 2)
2927
+ });
2928
+ entries.push({
2929
+ name: `${folderName}/summary.json`,
2930
+ data: JSON.stringify(summary, null, 2)
2931
+ });
2932
+ manifestRows.push({
2933
+ trajectoryId,
2934
+ folder: folderName,
2935
+ createdAt: summary.createdAt
2936
+ });
2937
+ }
2938
+ entries.unshift({
2939
+ name: "manifest.json",
2940
+ data: JSON.stringify({
2941
+ exportedAt: new Date().toISOString(),
2942
+ trajectories: manifestRows
2943
+ }, null, 2)
2944
+ });
2945
+ const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
2946
+ return {
2947
+ filename: `trajectories-${timestamp}.zip`,
2948
+ entries
2949
+ };
2950
+ }
2719
2951
  async exportTrajectories(options) {
2720
2952
  const runtime = this.runtime;
2721
2953
  if (!runtime?.adapter) {
@@ -2770,18 +3002,7 @@ class TrajectoryLoggerService extends Service {
2770
3002
  }
2771
3003
  let exportData = trajectories;
2772
3004
  if (!options.includePrompts) {
2773
- exportData = trajectories.map((t) => ({
2774
- ...t,
2775
- steps: t.steps.map((s) => ({
2776
- ...s,
2777
- llmCalls: s.llmCalls.map((c) => ({
2778
- ...c,
2779
- systemPrompt: "[redacted]",
2780
- userPrompt: "[redacted]",
2781
- response: "[redacted]"
2782
- }))
2783
- }))
2784
- }));
3005
+ exportData = trajectories.map((trajectory) => this.redactTrajectoryPrompts(trajectory));
2785
3006
  }
2786
3007
  return {
2787
3008
  data: JSON.stringify(exportData, null, 2),
@@ -3445,11 +3666,101 @@ async function scoreTrajectoryGroup(trajectories) {
3445
3666
  }
3446
3667
 
3447
3668
  // index.ts
3669
+ var pendingTrajectoryStepByReplyId = new Map;
3670
+ var pendingTrajectoryEndTargetByStepId = new Map;
3448
3671
  var trajectoryLoggerPlugin = {
3449
3672
  name: "@elizaos/plugin-trajectory-logger",
3450
3673
  description: "Captures and persists complete agent interaction trajectories for debugging, analysis, and RL training. " + "Records LLM calls, provider accesses, actions, environment state, and computes rewards.",
3451
3674
  dependencies: ["@elizaos/plugin-sql"],
3452
- services: [TrajectoryLoggerService]
3675
+ services: [TrajectoryLoggerService],
3676
+ events: {
3677
+ MESSAGE_RECEIVED: [
3678
+ async (payload) => {
3679
+ const { runtime, message, source } = payload;
3680
+ if (!message || !runtime)
3681
+ return;
3682
+ if (!message.metadata) {
3683
+ message.metadata = {
3684
+ type: "message"
3685
+ };
3686
+ }
3687
+ const meta = message.metadata;
3688
+ const logger5 = runtime.getService("trajectory_logger");
3689
+ if (!logger5)
3690
+ return;
3691
+ let trajectoryStepId = crypto.randomUUID();
3692
+ meta.trajectoryStepId = trajectoryStepId;
3693
+ try {
3694
+ const trajectoryId = await logger5.startTrajectory(runtime.agentId, {
3695
+ source: source ?? meta.source ?? "chat",
3696
+ metadata: {
3697
+ roomId: message.roomId,
3698
+ entityId: message.entityId,
3699
+ messageId: message.id,
3700
+ channelType: meta.channelType ?? message.content?.channelType,
3701
+ conversationId: meta.sessionKey
3702
+ }
3703
+ });
3704
+ const normalizedTrajectoryId = typeof trajectoryId === "string" && trajectoryId.trim().length > 0 ? trajectoryId : null;
3705
+ if (normalizedTrajectoryId) {
3706
+ const runtimeStepId = logger5.startStep(normalizedTrajectoryId, {
3707
+ timestamp: Date.now(),
3708
+ agentBalance: 0,
3709
+ agentPoints: 0,
3710
+ agentPnL: 0,
3711
+ openPositions: 0
3712
+ });
3713
+ const normalizedStepId = typeof runtimeStepId === "string" && runtimeStepId.trim().length > 0 ? runtimeStepId : trajectoryStepId;
3714
+ trajectoryStepId = normalizedStepId;
3715
+ meta.trajectoryStepId = trajectoryStepId;
3716
+ pendingTrajectoryEndTargetByStepId.set(trajectoryStepId, normalizedTrajectoryId);
3717
+ } else {}
3718
+ if (message.id) {
3719
+ const replyId = createUniqueUuid(runtime, message.id);
3720
+ pendingTrajectoryStepByReplyId.set(replyId, trajectoryStepId);
3721
+ }
3722
+ } catch (err) {
3723
+ runtime.logger?.warn({
3724
+ err,
3725
+ src: "plugin-trajectory-logger",
3726
+ roomId: message.roomId
3727
+ }, "Failed to start trajectory logging");
3728
+ }
3729
+ }
3730
+ ],
3731
+ MESSAGE_SENT: [
3732
+ async (payload) => {
3733
+ const { runtime, message } = payload;
3734
+ if (!message || !runtime)
3735
+ return;
3736
+ const meta = message.metadata;
3737
+ const inReplyTo = typeof message.content === "object" && message.content !== null && "inReplyTo" in message.content && typeof message.content.inReplyTo === "string" ? message.content.inReplyTo : undefined;
3738
+ let trajectoryStepId = meta?.trajectoryStepId;
3739
+ if (!trajectoryStepId && inReplyTo) {
3740
+ trajectoryStepId = pendingTrajectoryStepByReplyId.get(inReplyTo);
3741
+ }
3742
+ if (!trajectoryStepId)
3743
+ return;
3744
+ const logger5 = runtime.getService("trajectory_logger");
3745
+ if (!logger5)
3746
+ return;
3747
+ try {
3748
+ const endTarget = pendingTrajectoryEndTargetByStepId.get(trajectoryStepId) ?? trajectoryStepId;
3749
+ await logger5.endTrajectory(endTarget, "completed");
3750
+ } catch (err) {
3751
+ runtime.logger?.warn({
3752
+ err,
3753
+ src: "plugin-trajectory-logger",
3754
+ trajectoryStepId
3755
+ }, "Failed to end trajectory logging");
3756
+ }
3757
+ if (inReplyTo) {
3758
+ pendingTrajectoryStepByReplyId.delete(inReplyTo);
3759
+ }
3760
+ pendingTrajectoryEndTargetByStepId.delete(trajectoryStepId);
3761
+ }
3762
+ ]
3763
+ }
3453
3764
  };
3454
3765
  var typescript_default = trajectoryLoggerPlugin;
3455
3766
  export {
@@ -3492,4 +3803,4 @@ export {
3492
3803
  RewardService
3493
3804
  };
3494
3805
 
3495
- //# debugId=29EE15F427B068BA64756E2164756E21
3806
+ //# debugId=CDC29521B99CF06F64756E2164756E21