@elizaos/plugin-trajectory-logger 2.0.0-alpha.13 → 2.0.0-alpha.15
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.
- package/dist/node/index.node.js +3291 -173
- package/dist/node/index.node.js.map +36 -6
- package/package.json +10 -10
package/dist/node/index.node.js
CHANGED
|
@@ -1,198 +1,3306 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __export = (target, all) => {
|
|
3
|
+
for (var name in all)
|
|
4
|
+
__defProp(target, name, {
|
|
5
|
+
get: all[name],
|
|
6
|
+
enumerable: true,
|
|
7
|
+
configurable: true,
|
|
8
|
+
set: (newValue) => all[name] = () => newValue
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
12
|
+
|
|
13
|
+
// ../../../../node_modules/drizzle-orm/entity.js
|
|
14
|
+
function is(value, type) {
|
|
15
|
+
if (!value || typeof value !== "object") {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
if (value instanceof type) {
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
if (!Object.prototype.hasOwnProperty.call(type, entityKind)) {
|
|
22
|
+
throw new Error(`Class "${type.name ?? "<unknown>"}" doesn't look like a Drizzle entity. If this is incorrect and the class is provided by Drizzle, please report this as a bug.`);
|
|
23
|
+
}
|
|
24
|
+
let cls = Object.getPrototypeOf(value).constructor;
|
|
25
|
+
if (cls) {
|
|
26
|
+
while (cls) {
|
|
27
|
+
if (entityKind in cls && cls[entityKind] === type[entityKind]) {
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
cls = Object.getPrototypeOf(cls);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
var entityKind, hasOwnEntityKind;
|
|
36
|
+
var init_entity = __esm(() => {
|
|
37
|
+
entityKind = Symbol.for("drizzle:entityKind");
|
|
38
|
+
hasOwnEntityKind = Symbol.for("drizzle:hasOwnEntityKind");
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// ../../../../node_modules/drizzle-orm/column.js
|
|
42
|
+
var Column;
|
|
43
|
+
var init_column = __esm(() => {
|
|
44
|
+
init_entity();
|
|
45
|
+
Column = class Column {
|
|
46
|
+
constructor(table, config) {
|
|
47
|
+
this.table = table;
|
|
48
|
+
this.config = config;
|
|
49
|
+
this.name = config.name;
|
|
50
|
+
this.keyAsName = config.keyAsName;
|
|
51
|
+
this.notNull = config.notNull;
|
|
52
|
+
this.default = config.default;
|
|
53
|
+
this.defaultFn = config.defaultFn;
|
|
54
|
+
this.onUpdateFn = config.onUpdateFn;
|
|
55
|
+
this.hasDefault = config.hasDefault;
|
|
56
|
+
this.primary = config.primaryKey;
|
|
57
|
+
this.isUnique = config.isUnique;
|
|
58
|
+
this.uniqueName = config.uniqueName;
|
|
59
|
+
this.uniqueType = config.uniqueType;
|
|
60
|
+
this.dataType = config.dataType;
|
|
61
|
+
this.columnType = config.columnType;
|
|
62
|
+
this.generated = config.generated;
|
|
63
|
+
this.generatedIdentity = config.generatedIdentity;
|
|
64
|
+
}
|
|
65
|
+
static [entityKind] = "Column";
|
|
66
|
+
name;
|
|
67
|
+
keyAsName;
|
|
68
|
+
primary;
|
|
69
|
+
notNull;
|
|
70
|
+
default;
|
|
71
|
+
defaultFn;
|
|
72
|
+
onUpdateFn;
|
|
73
|
+
hasDefault;
|
|
74
|
+
isUnique;
|
|
75
|
+
uniqueName;
|
|
76
|
+
uniqueType;
|
|
77
|
+
dataType;
|
|
78
|
+
columnType;
|
|
79
|
+
enumValues = undefined;
|
|
80
|
+
generated = undefined;
|
|
81
|
+
generatedIdentity = undefined;
|
|
82
|
+
config;
|
|
83
|
+
mapFromDriverValue(value) {
|
|
84
|
+
return value;
|
|
85
|
+
}
|
|
86
|
+
mapToDriverValue(value) {
|
|
87
|
+
return value;
|
|
88
|
+
}
|
|
89
|
+
shouldDisableInsert() {
|
|
90
|
+
return this.config.generated !== undefined && this.config.generated.type !== "byDefault";
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// ../../../../node_modules/drizzle-orm/column-builder.js
|
|
96
|
+
var ColumnBuilder;
|
|
97
|
+
var init_column_builder = __esm(() => {
|
|
98
|
+
init_entity();
|
|
99
|
+
ColumnBuilder = class ColumnBuilder {
|
|
100
|
+
static [entityKind] = "ColumnBuilder";
|
|
101
|
+
config;
|
|
102
|
+
constructor(name, dataType, columnType) {
|
|
103
|
+
this.config = {
|
|
104
|
+
name,
|
|
105
|
+
keyAsName: name === "",
|
|
106
|
+
notNull: false,
|
|
107
|
+
default: undefined,
|
|
108
|
+
hasDefault: false,
|
|
109
|
+
primaryKey: false,
|
|
110
|
+
isUnique: false,
|
|
111
|
+
uniqueName: undefined,
|
|
112
|
+
uniqueType: undefined,
|
|
113
|
+
dataType,
|
|
114
|
+
columnType,
|
|
115
|
+
generated: undefined
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
$type() {
|
|
119
|
+
return this;
|
|
120
|
+
}
|
|
121
|
+
notNull() {
|
|
122
|
+
this.config.notNull = true;
|
|
123
|
+
return this;
|
|
124
|
+
}
|
|
125
|
+
default(value) {
|
|
126
|
+
this.config.default = value;
|
|
127
|
+
this.config.hasDefault = true;
|
|
128
|
+
return this;
|
|
129
|
+
}
|
|
130
|
+
$defaultFn(fn) {
|
|
131
|
+
this.config.defaultFn = fn;
|
|
132
|
+
this.config.hasDefault = true;
|
|
133
|
+
return this;
|
|
134
|
+
}
|
|
135
|
+
$default = this.$defaultFn;
|
|
136
|
+
$onUpdateFn(fn) {
|
|
137
|
+
this.config.onUpdateFn = fn;
|
|
138
|
+
this.config.hasDefault = true;
|
|
139
|
+
return this;
|
|
140
|
+
}
|
|
141
|
+
$onUpdate = this.$onUpdateFn;
|
|
142
|
+
primaryKey() {
|
|
143
|
+
this.config.primaryKey = true;
|
|
144
|
+
this.config.notNull = true;
|
|
145
|
+
return this;
|
|
146
|
+
}
|
|
147
|
+
setName(name) {
|
|
148
|
+
if (this.config.name !== "")
|
|
149
|
+
return;
|
|
150
|
+
this.config.name = name;
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
// ../../../../node_modules/drizzle-orm/table.utils.js
|
|
156
|
+
var TableName;
|
|
157
|
+
var init_table_utils = __esm(() => {
|
|
158
|
+
TableName = Symbol.for("drizzle:Name");
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
// ../../../../node_modules/drizzle-orm/tracing-utils.js
|
|
162
|
+
function iife(fn, ...args) {
|
|
163
|
+
return fn(...args);
|
|
164
|
+
}
|
|
165
|
+
var init_tracing_utils = () => {};
|
|
166
|
+
|
|
167
|
+
// ../../../../node_modules/drizzle-orm/pg-core/unique-constraint.js
|
|
168
|
+
function uniqueKeyName(table, columns) {
|
|
169
|
+
return `${table[TableName]}_${columns.join("_")}_unique`;
|
|
170
|
+
}
|
|
171
|
+
var init_unique_constraint = __esm(() => {
|
|
172
|
+
init_table_utils();
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
// ../../../../node_modules/drizzle-orm/pg-core/columns/common.js
|
|
176
|
+
var PgColumn, ExtraConfigColumn;
|
|
177
|
+
var init_common = __esm(() => {
|
|
178
|
+
init_column();
|
|
179
|
+
init_entity();
|
|
180
|
+
init_unique_constraint();
|
|
181
|
+
PgColumn = class PgColumn extends Column {
|
|
182
|
+
constructor(table, config) {
|
|
183
|
+
if (!config.uniqueName) {
|
|
184
|
+
config.uniqueName = uniqueKeyName(table, [config.name]);
|
|
185
|
+
}
|
|
186
|
+
super(table, config);
|
|
187
|
+
this.table = table;
|
|
188
|
+
}
|
|
189
|
+
static [entityKind] = "PgColumn";
|
|
190
|
+
};
|
|
191
|
+
ExtraConfigColumn = class ExtraConfigColumn extends PgColumn {
|
|
192
|
+
static [entityKind] = "ExtraConfigColumn";
|
|
193
|
+
getSQLType() {
|
|
194
|
+
return this.getSQLType();
|
|
195
|
+
}
|
|
196
|
+
indexConfig = {
|
|
197
|
+
order: this.config.order ?? "asc",
|
|
198
|
+
nulls: this.config.nulls ?? "last",
|
|
199
|
+
opClass: this.config.opClass
|
|
200
|
+
};
|
|
201
|
+
defaultConfig = {
|
|
202
|
+
order: "asc",
|
|
203
|
+
nulls: "last",
|
|
204
|
+
opClass: undefined
|
|
205
|
+
};
|
|
206
|
+
asc() {
|
|
207
|
+
this.indexConfig.order = "asc";
|
|
208
|
+
return this;
|
|
209
|
+
}
|
|
210
|
+
desc() {
|
|
211
|
+
this.indexConfig.order = "desc";
|
|
212
|
+
return this;
|
|
213
|
+
}
|
|
214
|
+
nullsFirst() {
|
|
215
|
+
this.indexConfig.nulls = "first";
|
|
216
|
+
return this;
|
|
217
|
+
}
|
|
218
|
+
nullsLast() {
|
|
219
|
+
this.indexConfig.nulls = "last";
|
|
220
|
+
return this;
|
|
221
|
+
}
|
|
222
|
+
op(opClass) {
|
|
223
|
+
this.indexConfig.opClass = opClass;
|
|
224
|
+
return this;
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
// ../../../../node_modules/drizzle-orm/pg-core/columns/enum.js
|
|
230
|
+
function isPgEnum(obj) {
|
|
231
|
+
return !!obj && typeof obj === "function" && isPgEnumSym in obj && obj[isPgEnumSym] === true;
|
|
232
|
+
}
|
|
233
|
+
var PgEnumObjectColumn, isPgEnumSym, PgEnumColumn;
|
|
234
|
+
var init_enum = __esm(() => {
|
|
235
|
+
init_entity();
|
|
236
|
+
init_common();
|
|
237
|
+
PgEnumObjectColumn = class PgEnumObjectColumn extends PgColumn {
|
|
238
|
+
static [entityKind] = "PgEnumObjectColumn";
|
|
239
|
+
enum;
|
|
240
|
+
enumValues = this.config.enum.enumValues;
|
|
241
|
+
constructor(table, config) {
|
|
242
|
+
super(table, config);
|
|
243
|
+
this.enum = config.enum;
|
|
244
|
+
}
|
|
245
|
+
getSQLType() {
|
|
246
|
+
return this.enum.enumName;
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
isPgEnumSym = Symbol.for("drizzle:isPgEnum");
|
|
250
|
+
PgEnumColumn = class PgEnumColumn extends PgColumn {
|
|
251
|
+
static [entityKind] = "PgEnumColumn";
|
|
252
|
+
enum = this.config.enum;
|
|
253
|
+
enumValues = this.config.enum.enumValues;
|
|
254
|
+
constructor(table, config) {
|
|
255
|
+
super(table, config);
|
|
256
|
+
this.enum = config.enum;
|
|
257
|
+
}
|
|
258
|
+
getSQLType() {
|
|
259
|
+
return this.enum.enumName;
|
|
260
|
+
}
|
|
261
|
+
};
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
// ../../../../node_modules/drizzle-orm/subquery.js
|
|
265
|
+
var Subquery, WithSubquery;
|
|
266
|
+
var init_subquery = __esm(() => {
|
|
267
|
+
init_entity();
|
|
268
|
+
Subquery = class Subquery {
|
|
269
|
+
static [entityKind] = "Subquery";
|
|
270
|
+
constructor(sql, fields, alias, isWith = false, usedTables = []) {
|
|
271
|
+
this._ = {
|
|
272
|
+
brand: "Subquery",
|
|
273
|
+
sql,
|
|
274
|
+
selectedFields: fields,
|
|
275
|
+
alias,
|
|
276
|
+
isWith,
|
|
277
|
+
usedTables
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
};
|
|
281
|
+
WithSubquery = class WithSubquery extends Subquery {
|
|
282
|
+
static [entityKind] = "WithSubquery";
|
|
283
|
+
};
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
// ../../../../node_modules/drizzle-orm/version.js
|
|
287
|
+
var version = "0.45.1";
|
|
288
|
+
var init_version = () => {};
|
|
289
|
+
|
|
290
|
+
// ../../../../node_modules/drizzle-orm/tracing.js
|
|
291
|
+
var otel, rawTracer, tracer;
|
|
292
|
+
var init_tracing = __esm(() => {
|
|
293
|
+
init_tracing_utils();
|
|
294
|
+
init_version();
|
|
295
|
+
tracer = {
|
|
296
|
+
startActiveSpan(name, fn) {
|
|
297
|
+
if (!otel) {
|
|
298
|
+
return fn();
|
|
299
|
+
}
|
|
300
|
+
if (!rawTracer) {
|
|
301
|
+
rawTracer = otel.trace.getTracer("drizzle-orm", version);
|
|
302
|
+
}
|
|
303
|
+
return iife((otel2, rawTracer2) => rawTracer2.startActiveSpan(name, (span) => {
|
|
304
|
+
try {
|
|
305
|
+
return fn(span);
|
|
306
|
+
} catch (e) {
|
|
307
|
+
span.setStatus({
|
|
308
|
+
code: otel2.SpanStatusCode.ERROR,
|
|
309
|
+
message: e instanceof Error ? e.message : "Unknown error"
|
|
310
|
+
});
|
|
311
|
+
throw e;
|
|
312
|
+
} finally {
|
|
313
|
+
span.end();
|
|
314
|
+
}
|
|
315
|
+
}), otel, rawTracer);
|
|
316
|
+
}
|
|
317
|
+
};
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
// ../../../../node_modules/drizzle-orm/view-common.js
|
|
321
|
+
var ViewBaseConfig;
|
|
322
|
+
var init_view_common = __esm(() => {
|
|
323
|
+
ViewBaseConfig = Symbol.for("drizzle:ViewBaseConfig");
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
// ../../../../node_modules/drizzle-orm/table.js
|
|
327
|
+
function isTable(table) {
|
|
328
|
+
return typeof table === "object" && table !== null && IsDrizzleTable in table;
|
|
329
|
+
}
|
|
330
|
+
function getTableName(table) {
|
|
331
|
+
return table[TableName];
|
|
332
|
+
}
|
|
333
|
+
function getTableUniqueName(table) {
|
|
334
|
+
return `${table[Schema] ?? "public"}.${table[TableName]}`;
|
|
335
|
+
}
|
|
336
|
+
var Schema, Columns, ExtraConfigColumns, OriginalName, BaseName, IsAlias, ExtraConfigBuilder, IsDrizzleTable, Table;
|
|
337
|
+
var init_table = __esm(() => {
|
|
338
|
+
init_entity();
|
|
339
|
+
init_table_utils();
|
|
340
|
+
Schema = Symbol.for("drizzle:Schema");
|
|
341
|
+
Columns = Symbol.for("drizzle:Columns");
|
|
342
|
+
ExtraConfigColumns = Symbol.for("drizzle:ExtraConfigColumns");
|
|
343
|
+
OriginalName = Symbol.for("drizzle:OriginalName");
|
|
344
|
+
BaseName = Symbol.for("drizzle:BaseName");
|
|
345
|
+
IsAlias = Symbol.for("drizzle:IsAlias");
|
|
346
|
+
ExtraConfigBuilder = Symbol.for("drizzle:ExtraConfigBuilder");
|
|
347
|
+
IsDrizzleTable = Symbol.for("drizzle:IsDrizzleTable");
|
|
348
|
+
Table = class Table {
|
|
349
|
+
static [entityKind] = "Table";
|
|
350
|
+
static Symbol = {
|
|
351
|
+
Name: TableName,
|
|
352
|
+
Schema,
|
|
353
|
+
OriginalName,
|
|
354
|
+
Columns,
|
|
355
|
+
ExtraConfigColumns,
|
|
356
|
+
BaseName,
|
|
357
|
+
IsAlias,
|
|
358
|
+
ExtraConfigBuilder
|
|
359
|
+
};
|
|
360
|
+
[TableName];
|
|
361
|
+
[OriginalName];
|
|
362
|
+
[Schema];
|
|
363
|
+
[Columns];
|
|
364
|
+
[ExtraConfigColumns];
|
|
365
|
+
[BaseName];
|
|
366
|
+
[IsAlias] = false;
|
|
367
|
+
[IsDrizzleTable] = true;
|
|
368
|
+
[ExtraConfigBuilder] = undefined;
|
|
369
|
+
constructor(name, schema, baseName) {
|
|
370
|
+
this[TableName] = this[OriginalName] = name;
|
|
371
|
+
this[Schema] = schema;
|
|
372
|
+
this[BaseName] = baseName;
|
|
373
|
+
}
|
|
374
|
+
};
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
// ../../../../node_modules/drizzle-orm/sql/sql.js
|
|
378
|
+
function isSQLWrapper(value) {
|
|
379
|
+
return value !== null && value !== undefined && typeof value.getSQL === "function";
|
|
380
|
+
}
|
|
381
|
+
function mergeQueries(queries) {
|
|
382
|
+
const result = { sql: "", params: [] };
|
|
383
|
+
for (const query of queries) {
|
|
384
|
+
result.sql += query.sql;
|
|
385
|
+
result.params.push(...query.params);
|
|
386
|
+
if (query.typings?.length) {
|
|
387
|
+
if (!result.typings) {
|
|
388
|
+
result.typings = [];
|
|
389
|
+
}
|
|
390
|
+
result.typings.push(...query.typings);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
return result;
|
|
394
|
+
}
|
|
395
|
+
function name(value) {
|
|
396
|
+
return new Name(value);
|
|
397
|
+
}
|
|
398
|
+
function isDriverValueEncoder(value) {
|
|
399
|
+
return typeof value === "object" && value !== null && "mapToDriverValue" in value && typeof value.mapToDriverValue === "function";
|
|
400
|
+
}
|
|
401
|
+
function param(value, encoder) {
|
|
402
|
+
return new Param(value, encoder);
|
|
403
|
+
}
|
|
404
|
+
function sql(strings, ...params) {
|
|
405
|
+
const queryChunks = [];
|
|
406
|
+
if (params.length > 0 || strings.length > 0 && strings[0] !== "") {
|
|
407
|
+
queryChunks.push(new StringChunk(strings[0]));
|
|
408
|
+
}
|
|
409
|
+
for (const [paramIndex, param2] of params.entries()) {
|
|
410
|
+
queryChunks.push(param2, new StringChunk(strings[paramIndex + 1]));
|
|
411
|
+
}
|
|
412
|
+
return new SQL(queryChunks);
|
|
413
|
+
}
|
|
414
|
+
function placeholder(name2) {
|
|
415
|
+
return new Placeholder(name2);
|
|
416
|
+
}
|
|
417
|
+
function fillPlaceholders(params, values) {
|
|
418
|
+
return params.map((p) => {
|
|
419
|
+
if (is(p, Placeholder)) {
|
|
420
|
+
if (!(p.name in values)) {
|
|
421
|
+
throw new Error(`No value for placeholder "${p.name}" was provided`);
|
|
422
|
+
}
|
|
423
|
+
return values[p.name];
|
|
424
|
+
}
|
|
425
|
+
if (is(p, Param) && is(p.value, Placeholder)) {
|
|
426
|
+
if (!(p.value.name in values)) {
|
|
427
|
+
throw new Error(`No value for placeholder "${p.value.name}" was provided`);
|
|
428
|
+
}
|
|
429
|
+
return p.encoder.mapToDriverValue(values[p.value.name]);
|
|
430
|
+
}
|
|
431
|
+
return p;
|
|
432
|
+
});
|
|
433
|
+
}
|
|
434
|
+
function isView(view) {
|
|
435
|
+
return typeof view === "object" && view !== null && IsDrizzleView in view;
|
|
436
|
+
}
|
|
437
|
+
function getViewName(view) {
|
|
438
|
+
return view[ViewBaseConfig].name;
|
|
439
|
+
}
|
|
440
|
+
var FakePrimitiveParam, StringChunk, SQL, Name, noopDecoder, noopEncoder, noopMapper, Param, Placeholder, IsDrizzleView, View;
|
|
441
|
+
var init_sql = __esm(() => {
|
|
442
|
+
init_entity();
|
|
443
|
+
init_enum();
|
|
444
|
+
init_subquery();
|
|
445
|
+
init_tracing();
|
|
446
|
+
init_view_common();
|
|
447
|
+
init_column();
|
|
448
|
+
init_table();
|
|
449
|
+
FakePrimitiveParam = class FakePrimitiveParam {
|
|
450
|
+
static [entityKind] = "FakePrimitiveParam";
|
|
451
|
+
};
|
|
452
|
+
StringChunk = class StringChunk {
|
|
453
|
+
static [entityKind] = "StringChunk";
|
|
454
|
+
value;
|
|
455
|
+
constructor(value) {
|
|
456
|
+
this.value = Array.isArray(value) ? value : [value];
|
|
457
|
+
}
|
|
458
|
+
getSQL() {
|
|
459
|
+
return new SQL([this]);
|
|
460
|
+
}
|
|
461
|
+
};
|
|
462
|
+
SQL = class SQL {
|
|
463
|
+
constructor(queryChunks) {
|
|
464
|
+
this.queryChunks = queryChunks;
|
|
465
|
+
for (const chunk of queryChunks) {
|
|
466
|
+
if (is(chunk, Table)) {
|
|
467
|
+
const schemaName = chunk[Table.Symbol.Schema];
|
|
468
|
+
this.usedTables.push(schemaName === undefined ? chunk[Table.Symbol.Name] : schemaName + "." + chunk[Table.Symbol.Name]);
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
static [entityKind] = "SQL";
|
|
473
|
+
decoder = noopDecoder;
|
|
474
|
+
shouldInlineParams = false;
|
|
475
|
+
usedTables = [];
|
|
476
|
+
append(query) {
|
|
477
|
+
this.queryChunks.push(...query.queryChunks);
|
|
478
|
+
return this;
|
|
479
|
+
}
|
|
480
|
+
toQuery(config) {
|
|
481
|
+
return tracer.startActiveSpan("drizzle.buildSQL", (span) => {
|
|
482
|
+
const query = this.buildQueryFromSourceParams(this.queryChunks, config);
|
|
483
|
+
span?.setAttributes({
|
|
484
|
+
"drizzle.query.text": query.sql,
|
|
485
|
+
"drizzle.query.params": JSON.stringify(query.params)
|
|
486
|
+
});
|
|
487
|
+
return query;
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
buildQueryFromSourceParams(chunks, _config) {
|
|
491
|
+
const config = Object.assign({}, _config, {
|
|
492
|
+
inlineParams: _config.inlineParams || this.shouldInlineParams,
|
|
493
|
+
paramStartIndex: _config.paramStartIndex || { value: 0 }
|
|
494
|
+
});
|
|
495
|
+
const {
|
|
496
|
+
casing,
|
|
497
|
+
escapeName,
|
|
498
|
+
escapeParam,
|
|
499
|
+
prepareTyping,
|
|
500
|
+
inlineParams,
|
|
501
|
+
paramStartIndex
|
|
502
|
+
} = config;
|
|
503
|
+
return mergeQueries(chunks.map((chunk) => {
|
|
504
|
+
if (is(chunk, StringChunk)) {
|
|
505
|
+
return { sql: chunk.value.join(""), params: [] };
|
|
506
|
+
}
|
|
507
|
+
if (is(chunk, Name)) {
|
|
508
|
+
return { sql: escapeName(chunk.value), params: [] };
|
|
509
|
+
}
|
|
510
|
+
if (chunk === undefined) {
|
|
511
|
+
return { sql: "", params: [] };
|
|
512
|
+
}
|
|
513
|
+
if (Array.isArray(chunk)) {
|
|
514
|
+
const result = [new StringChunk("(")];
|
|
515
|
+
for (const [i, p] of chunk.entries()) {
|
|
516
|
+
result.push(p);
|
|
517
|
+
if (i < chunk.length - 1) {
|
|
518
|
+
result.push(new StringChunk(", "));
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
result.push(new StringChunk(")"));
|
|
522
|
+
return this.buildQueryFromSourceParams(result, config);
|
|
523
|
+
}
|
|
524
|
+
if (is(chunk, SQL)) {
|
|
525
|
+
return this.buildQueryFromSourceParams(chunk.queryChunks, {
|
|
526
|
+
...config,
|
|
527
|
+
inlineParams: inlineParams || chunk.shouldInlineParams
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
if (is(chunk, Table)) {
|
|
531
|
+
const schemaName = chunk[Table.Symbol.Schema];
|
|
532
|
+
const tableName = chunk[Table.Symbol.Name];
|
|
533
|
+
return {
|
|
534
|
+
sql: schemaName === undefined || chunk[IsAlias] ? escapeName(tableName) : escapeName(schemaName) + "." + escapeName(tableName),
|
|
535
|
+
params: []
|
|
536
|
+
};
|
|
537
|
+
}
|
|
538
|
+
if (is(chunk, Column)) {
|
|
539
|
+
const columnName = casing.getColumnCasing(chunk);
|
|
540
|
+
if (_config.invokeSource === "indexes") {
|
|
541
|
+
return { sql: escapeName(columnName), params: [] };
|
|
542
|
+
}
|
|
543
|
+
const schemaName = chunk.table[Table.Symbol.Schema];
|
|
544
|
+
return {
|
|
545
|
+
sql: chunk.table[IsAlias] || schemaName === undefined ? escapeName(chunk.table[Table.Symbol.Name]) + "." + escapeName(columnName) : escapeName(schemaName) + "." + escapeName(chunk.table[Table.Symbol.Name]) + "." + escapeName(columnName),
|
|
546
|
+
params: []
|
|
547
|
+
};
|
|
548
|
+
}
|
|
549
|
+
if (is(chunk, View)) {
|
|
550
|
+
const schemaName = chunk[ViewBaseConfig].schema;
|
|
551
|
+
const viewName = chunk[ViewBaseConfig].name;
|
|
552
|
+
return {
|
|
553
|
+
sql: schemaName === undefined || chunk[ViewBaseConfig].isAlias ? escapeName(viewName) : escapeName(schemaName) + "." + escapeName(viewName),
|
|
554
|
+
params: []
|
|
555
|
+
};
|
|
556
|
+
}
|
|
557
|
+
if (is(chunk, Param)) {
|
|
558
|
+
if (is(chunk.value, Placeholder)) {
|
|
559
|
+
return { sql: escapeParam(paramStartIndex.value++, chunk), params: [chunk], typings: ["none"] };
|
|
560
|
+
}
|
|
561
|
+
const mappedValue = chunk.value === null ? null : chunk.encoder.mapToDriverValue(chunk.value);
|
|
562
|
+
if (is(mappedValue, SQL)) {
|
|
563
|
+
return this.buildQueryFromSourceParams([mappedValue], config);
|
|
564
|
+
}
|
|
565
|
+
if (inlineParams) {
|
|
566
|
+
return { sql: this.mapInlineParam(mappedValue, config), params: [] };
|
|
567
|
+
}
|
|
568
|
+
let typings = ["none"];
|
|
569
|
+
if (prepareTyping) {
|
|
570
|
+
typings = [prepareTyping(chunk.encoder)];
|
|
571
|
+
}
|
|
572
|
+
return { sql: escapeParam(paramStartIndex.value++, mappedValue), params: [mappedValue], typings };
|
|
573
|
+
}
|
|
574
|
+
if (is(chunk, Placeholder)) {
|
|
575
|
+
return { sql: escapeParam(paramStartIndex.value++, chunk), params: [chunk], typings: ["none"] };
|
|
576
|
+
}
|
|
577
|
+
if (is(chunk, SQL.Aliased) && chunk.fieldAlias !== undefined) {
|
|
578
|
+
return { sql: escapeName(chunk.fieldAlias), params: [] };
|
|
579
|
+
}
|
|
580
|
+
if (is(chunk, Subquery)) {
|
|
581
|
+
if (chunk._.isWith) {
|
|
582
|
+
return { sql: escapeName(chunk._.alias), params: [] };
|
|
583
|
+
}
|
|
584
|
+
return this.buildQueryFromSourceParams([
|
|
585
|
+
new StringChunk("("),
|
|
586
|
+
chunk._.sql,
|
|
587
|
+
new StringChunk(") "),
|
|
588
|
+
new Name(chunk._.alias)
|
|
589
|
+
], config);
|
|
590
|
+
}
|
|
591
|
+
if (isPgEnum(chunk)) {
|
|
592
|
+
if (chunk.schema) {
|
|
593
|
+
return { sql: escapeName(chunk.schema) + "." + escapeName(chunk.enumName), params: [] };
|
|
594
|
+
}
|
|
595
|
+
return { sql: escapeName(chunk.enumName), params: [] };
|
|
596
|
+
}
|
|
597
|
+
if (isSQLWrapper(chunk)) {
|
|
598
|
+
if (chunk.shouldOmitSQLParens?.()) {
|
|
599
|
+
return this.buildQueryFromSourceParams([chunk.getSQL()], config);
|
|
600
|
+
}
|
|
601
|
+
return this.buildQueryFromSourceParams([
|
|
602
|
+
new StringChunk("("),
|
|
603
|
+
chunk.getSQL(),
|
|
604
|
+
new StringChunk(")")
|
|
605
|
+
], config);
|
|
606
|
+
}
|
|
607
|
+
if (inlineParams) {
|
|
608
|
+
return { sql: this.mapInlineParam(chunk, config), params: [] };
|
|
609
|
+
}
|
|
610
|
+
return { sql: escapeParam(paramStartIndex.value++, chunk), params: [chunk], typings: ["none"] };
|
|
611
|
+
}));
|
|
612
|
+
}
|
|
613
|
+
mapInlineParam(chunk, { escapeString }) {
|
|
614
|
+
if (chunk === null) {
|
|
615
|
+
return "null";
|
|
616
|
+
}
|
|
617
|
+
if (typeof chunk === "number" || typeof chunk === "boolean") {
|
|
618
|
+
return chunk.toString();
|
|
619
|
+
}
|
|
620
|
+
if (typeof chunk === "string") {
|
|
621
|
+
return escapeString(chunk);
|
|
622
|
+
}
|
|
623
|
+
if (typeof chunk === "object") {
|
|
624
|
+
const mappedValueAsString = chunk.toString();
|
|
625
|
+
if (mappedValueAsString === "[object Object]") {
|
|
626
|
+
return escapeString(JSON.stringify(chunk));
|
|
627
|
+
}
|
|
628
|
+
return escapeString(mappedValueAsString);
|
|
629
|
+
}
|
|
630
|
+
throw new Error("Unexpected param value: " + chunk);
|
|
631
|
+
}
|
|
632
|
+
getSQL() {
|
|
633
|
+
return this;
|
|
634
|
+
}
|
|
635
|
+
as(alias) {
|
|
636
|
+
if (alias === undefined) {
|
|
637
|
+
return this;
|
|
638
|
+
}
|
|
639
|
+
return new SQL.Aliased(this, alias);
|
|
640
|
+
}
|
|
641
|
+
mapWith(decoder) {
|
|
642
|
+
this.decoder = typeof decoder === "function" ? { mapFromDriverValue: decoder } : decoder;
|
|
643
|
+
return this;
|
|
644
|
+
}
|
|
645
|
+
inlineParams() {
|
|
646
|
+
this.shouldInlineParams = true;
|
|
647
|
+
return this;
|
|
648
|
+
}
|
|
649
|
+
if(condition) {
|
|
650
|
+
return condition ? this : undefined;
|
|
651
|
+
}
|
|
652
|
+
};
|
|
653
|
+
Name = class Name {
|
|
654
|
+
constructor(value) {
|
|
655
|
+
this.value = value;
|
|
656
|
+
}
|
|
657
|
+
static [entityKind] = "Name";
|
|
658
|
+
brand;
|
|
659
|
+
getSQL() {
|
|
660
|
+
return new SQL([this]);
|
|
661
|
+
}
|
|
662
|
+
};
|
|
663
|
+
noopDecoder = {
|
|
664
|
+
mapFromDriverValue: (value) => value
|
|
665
|
+
};
|
|
666
|
+
noopEncoder = {
|
|
667
|
+
mapToDriverValue: (value) => value
|
|
668
|
+
};
|
|
669
|
+
noopMapper = {
|
|
670
|
+
...noopDecoder,
|
|
671
|
+
...noopEncoder
|
|
672
|
+
};
|
|
673
|
+
Param = class Param {
|
|
674
|
+
constructor(value, encoder = noopEncoder) {
|
|
675
|
+
this.value = value;
|
|
676
|
+
this.encoder = encoder;
|
|
677
|
+
}
|
|
678
|
+
static [entityKind] = "Param";
|
|
679
|
+
brand;
|
|
680
|
+
getSQL() {
|
|
681
|
+
return new SQL([this]);
|
|
682
|
+
}
|
|
683
|
+
};
|
|
684
|
+
((sql2) => {
|
|
685
|
+
function empty() {
|
|
686
|
+
return new SQL([]);
|
|
687
|
+
}
|
|
688
|
+
sql2.empty = empty;
|
|
689
|
+
function fromList(list) {
|
|
690
|
+
return new SQL(list);
|
|
691
|
+
}
|
|
692
|
+
sql2.fromList = fromList;
|
|
693
|
+
function raw(str) {
|
|
694
|
+
return new SQL([new StringChunk(str)]);
|
|
695
|
+
}
|
|
696
|
+
sql2.raw = raw;
|
|
697
|
+
function join(chunks, separator) {
|
|
698
|
+
const result = [];
|
|
699
|
+
for (const [i, chunk] of chunks.entries()) {
|
|
700
|
+
if (i > 0 && separator !== undefined) {
|
|
701
|
+
result.push(separator);
|
|
702
|
+
}
|
|
703
|
+
result.push(chunk);
|
|
704
|
+
}
|
|
705
|
+
return new SQL(result);
|
|
706
|
+
}
|
|
707
|
+
sql2.join = join;
|
|
708
|
+
function identifier(value) {
|
|
709
|
+
return new Name(value);
|
|
710
|
+
}
|
|
711
|
+
sql2.identifier = identifier;
|
|
712
|
+
function placeholder2(name2) {
|
|
713
|
+
return new Placeholder(name2);
|
|
714
|
+
}
|
|
715
|
+
sql2.placeholder = placeholder2;
|
|
716
|
+
function param2(value, encoder) {
|
|
717
|
+
return new Param(value, encoder);
|
|
718
|
+
}
|
|
719
|
+
sql2.param = param2;
|
|
720
|
+
})(sql || (sql = {}));
|
|
721
|
+
((SQL2) => {
|
|
722
|
+
|
|
723
|
+
class Aliased {
|
|
724
|
+
constructor(sql2, fieldAlias) {
|
|
725
|
+
this.sql = sql2;
|
|
726
|
+
this.fieldAlias = fieldAlias;
|
|
727
|
+
}
|
|
728
|
+
static [entityKind] = "SQL.Aliased";
|
|
729
|
+
isSelectionField = false;
|
|
730
|
+
getSQL() {
|
|
731
|
+
return this.sql;
|
|
732
|
+
}
|
|
733
|
+
clone() {
|
|
734
|
+
return new Aliased(this.sql, this.fieldAlias);
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
SQL2.Aliased = Aliased;
|
|
738
|
+
})(SQL || (SQL = {}));
|
|
739
|
+
Placeholder = class Placeholder {
|
|
740
|
+
constructor(name2) {
|
|
741
|
+
this.name = name2;
|
|
742
|
+
}
|
|
743
|
+
static [entityKind] = "Placeholder";
|
|
744
|
+
getSQL() {
|
|
745
|
+
return new SQL([this]);
|
|
746
|
+
}
|
|
747
|
+
};
|
|
748
|
+
IsDrizzleView = Symbol.for("drizzle:IsDrizzleView");
|
|
749
|
+
View = class View {
|
|
750
|
+
static [entityKind] = "View";
|
|
751
|
+
[ViewBaseConfig];
|
|
752
|
+
[IsDrizzleView] = true;
|
|
753
|
+
constructor({ name: name2, schema, selectedFields, query }) {
|
|
754
|
+
this[ViewBaseConfig] = {
|
|
755
|
+
name: name2,
|
|
756
|
+
originalName: name2,
|
|
757
|
+
schema,
|
|
758
|
+
selectedFields,
|
|
759
|
+
query,
|
|
760
|
+
isExisting: !query,
|
|
761
|
+
isAlias: false
|
|
762
|
+
};
|
|
763
|
+
}
|
|
764
|
+
getSQL() {
|
|
765
|
+
return new SQL([this]);
|
|
766
|
+
}
|
|
767
|
+
};
|
|
768
|
+
Column.prototype.getSQL = function() {
|
|
769
|
+
return new SQL([this]);
|
|
770
|
+
};
|
|
771
|
+
Table.prototype.getSQL = function() {
|
|
772
|
+
return new SQL([this]);
|
|
773
|
+
};
|
|
774
|
+
Subquery.prototype.getSQL = function() {
|
|
775
|
+
return new SQL([this]);
|
|
776
|
+
};
|
|
777
|
+
});
|
|
778
|
+
|
|
779
|
+
// ../../../../node_modules/drizzle-orm/alias.js
|
|
780
|
+
function aliasedTable(table, tableAlias) {
|
|
781
|
+
return new Proxy(table, new TableAliasProxyHandler(tableAlias, false));
|
|
782
|
+
}
|
|
783
|
+
function aliasedRelation(relation, tableAlias) {
|
|
784
|
+
return new Proxy(relation, new RelationTableAliasProxyHandler(tableAlias));
|
|
785
|
+
}
|
|
786
|
+
function aliasedTableColumn(column, tableAlias) {
|
|
787
|
+
return new Proxy(column, new ColumnAliasProxyHandler(new Proxy(column.table, new TableAliasProxyHandler(tableAlias, false))));
|
|
788
|
+
}
|
|
789
|
+
function mapColumnsInAliasedSQLToAlias(query, alias) {
|
|
790
|
+
return new SQL.Aliased(mapColumnsInSQLToAlias(query.sql, alias), query.fieldAlias);
|
|
791
|
+
}
|
|
792
|
+
function mapColumnsInSQLToAlias(query, alias) {
|
|
793
|
+
return sql.join(query.queryChunks.map((c) => {
|
|
794
|
+
if (is(c, Column)) {
|
|
795
|
+
return aliasedTableColumn(c, alias);
|
|
796
|
+
}
|
|
797
|
+
if (is(c, SQL)) {
|
|
798
|
+
return mapColumnsInSQLToAlias(c, alias);
|
|
799
|
+
}
|
|
800
|
+
if (is(c, SQL.Aliased)) {
|
|
801
|
+
return mapColumnsInAliasedSQLToAlias(c, alias);
|
|
802
|
+
}
|
|
803
|
+
return c;
|
|
804
|
+
}));
|
|
805
|
+
}
|
|
806
|
+
var ColumnAliasProxyHandler, TableAliasProxyHandler, RelationTableAliasProxyHandler;
|
|
807
|
+
var init_alias = __esm(() => {
|
|
808
|
+
init_column();
|
|
809
|
+
init_entity();
|
|
810
|
+
init_sql();
|
|
811
|
+
init_table();
|
|
812
|
+
init_view_common();
|
|
813
|
+
ColumnAliasProxyHandler = class ColumnAliasProxyHandler {
|
|
814
|
+
constructor(table) {
|
|
815
|
+
this.table = table;
|
|
816
|
+
}
|
|
817
|
+
static [entityKind] = "ColumnAliasProxyHandler";
|
|
818
|
+
get(columnObj, prop) {
|
|
819
|
+
if (prop === "table") {
|
|
820
|
+
return this.table;
|
|
821
|
+
}
|
|
822
|
+
return columnObj[prop];
|
|
823
|
+
}
|
|
824
|
+
};
|
|
825
|
+
TableAliasProxyHandler = class TableAliasProxyHandler {
|
|
826
|
+
constructor(alias, replaceOriginalName) {
|
|
827
|
+
this.alias = alias;
|
|
828
|
+
this.replaceOriginalName = replaceOriginalName;
|
|
829
|
+
}
|
|
830
|
+
static [entityKind] = "TableAliasProxyHandler";
|
|
831
|
+
get(target, prop) {
|
|
832
|
+
if (prop === Table.Symbol.IsAlias) {
|
|
833
|
+
return true;
|
|
834
|
+
}
|
|
835
|
+
if (prop === Table.Symbol.Name) {
|
|
836
|
+
return this.alias;
|
|
837
|
+
}
|
|
838
|
+
if (this.replaceOriginalName && prop === Table.Symbol.OriginalName) {
|
|
839
|
+
return this.alias;
|
|
840
|
+
}
|
|
841
|
+
if (prop === ViewBaseConfig) {
|
|
842
|
+
return {
|
|
843
|
+
...target[ViewBaseConfig],
|
|
844
|
+
name: this.alias,
|
|
845
|
+
isAlias: true
|
|
846
|
+
};
|
|
847
|
+
}
|
|
848
|
+
if (prop === Table.Symbol.Columns) {
|
|
849
|
+
const columns = target[Table.Symbol.Columns];
|
|
850
|
+
if (!columns) {
|
|
851
|
+
return columns;
|
|
852
|
+
}
|
|
853
|
+
const proxiedColumns = {};
|
|
854
|
+
Object.keys(columns).map((key) => {
|
|
855
|
+
proxiedColumns[key] = new Proxy(columns[key], new ColumnAliasProxyHandler(new Proxy(target, this)));
|
|
856
|
+
});
|
|
857
|
+
return proxiedColumns;
|
|
858
|
+
}
|
|
859
|
+
const value = target[prop];
|
|
860
|
+
if (is(value, Column)) {
|
|
861
|
+
return new Proxy(value, new ColumnAliasProxyHandler(new Proxy(target, this)));
|
|
862
|
+
}
|
|
863
|
+
return value;
|
|
864
|
+
}
|
|
865
|
+
};
|
|
866
|
+
RelationTableAliasProxyHandler = class RelationTableAliasProxyHandler {
|
|
867
|
+
constructor(alias) {
|
|
868
|
+
this.alias = alias;
|
|
869
|
+
}
|
|
870
|
+
static [entityKind] = "RelationTableAliasProxyHandler";
|
|
871
|
+
get(target, prop) {
|
|
872
|
+
if (prop === "sourceTable") {
|
|
873
|
+
return aliasedTable(target.sourceTable, this.alias);
|
|
874
|
+
}
|
|
875
|
+
return target[prop];
|
|
876
|
+
}
|
|
877
|
+
};
|
|
878
|
+
});
|
|
879
|
+
|
|
880
|
+
// ../../../../node_modules/drizzle-orm/errors.js
|
|
881
|
+
var DrizzleError, DrizzleQueryError, TransactionRollbackError;
|
|
882
|
+
var init_errors = __esm(() => {
|
|
883
|
+
init_entity();
|
|
884
|
+
DrizzleError = class DrizzleError extends Error {
|
|
885
|
+
static [entityKind] = "DrizzleError";
|
|
886
|
+
constructor({ message, cause }) {
|
|
887
|
+
super(message);
|
|
888
|
+
this.name = "DrizzleError";
|
|
889
|
+
this.cause = cause;
|
|
890
|
+
}
|
|
891
|
+
};
|
|
892
|
+
DrizzleQueryError = class DrizzleQueryError extends Error {
|
|
893
|
+
constructor(query, params, cause) {
|
|
894
|
+
super(`Failed query: ${query}
|
|
895
|
+
params: ${params}`);
|
|
896
|
+
this.query = query;
|
|
897
|
+
this.params = params;
|
|
898
|
+
this.cause = cause;
|
|
899
|
+
Error.captureStackTrace(this, DrizzleQueryError);
|
|
900
|
+
if (cause)
|
|
901
|
+
this.cause = cause;
|
|
902
|
+
}
|
|
903
|
+
};
|
|
904
|
+
TransactionRollbackError = class TransactionRollbackError extends DrizzleError {
|
|
905
|
+
static [entityKind] = "TransactionRollbackError";
|
|
906
|
+
constructor() {
|
|
907
|
+
super({ message: "Rollback" });
|
|
908
|
+
}
|
|
909
|
+
};
|
|
910
|
+
});
|
|
911
|
+
|
|
912
|
+
// ../../../../node_modules/drizzle-orm/logger.js
|
|
913
|
+
var ConsoleLogWriter, DefaultLogger, NoopLogger;
|
|
914
|
+
var init_logger = __esm(() => {
|
|
915
|
+
init_entity();
|
|
916
|
+
ConsoleLogWriter = class ConsoleLogWriter {
|
|
917
|
+
static [entityKind] = "ConsoleLogWriter";
|
|
918
|
+
write(message) {
|
|
919
|
+
console.log(message);
|
|
920
|
+
}
|
|
921
|
+
};
|
|
922
|
+
DefaultLogger = class DefaultLogger {
|
|
923
|
+
static [entityKind] = "DefaultLogger";
|
|
924
|
+
writer;
|
|
925
|
+
constructor(config) {
|
|
926
|
+
this.writer = config?.writer ?? new ConsoleLogWriter;
|
|
927
|
+
}
|
|
928
|
+
logQuery(query, params) {
|
|
929
|
+
const stringifiedParams = params.map((p) => {
|
|
930
|
+
try {
|
|
931
|
+
return JSON.stringify(p);
|
|
932
|
+
} catch {
|
|
933
|
+
return String(p);
|
|
934
|
+
}
|
|
935
|
+
});
|
|
936
|
+
const paramsStr = stringifiedParams.length ? ` -- params: [${stringifiedParams.join(", ")}]` : "";
|
|
937
|
+
this.writer.write(`Query: ${query}${paramsStr}`);
|
|
938
|
+
}
|
|
939
|
+
};
|
|
940
|
+
NoopLogger = class NoopLogger {
|
|
941
|
+
static [entityKind] = "NoopLogger";
|
|
942
|
+
logQuery() {}
|
|
943
|
+
};
|
|
944
|
+
});
|
|
945
|
+
|
|
946
|
+
// ../../../../node_modules/drizzle-orm/query-promise.js
|
|
947
|
+
var QueryPromise;
|
|
948
|
+
var init_query_promise = __esm(() => {
|
|
949
|
+
init_entity();
|
|
950
|
+
QueryPromise = class QueryPromise {
|
|
951
|
+
static [entityKind] = "QueryPromise";
|
|
952
|
+
[Symbol.toStringTag] = "QueryPromise";
|
|
953
|
+
catch(onRejected) {
|
|
954
|
+
return this.then(undefined, onRejected);
|
|
955
|
+
}
|
|
956
|
+
finally(onFinally) {
|
|
957
|
+
return this.then((value) => {
|
|
958
|
+
onFinally?.();
|
|
959
|
+
return value;
|
|
960
|
+
}, (reason) => {
|
|
961
|
+
onFinally?.();
|
|
962
|
+
throw reason;
|
|
963
|
+
});
|
|
964
|
+
}
|
|
965
|
+
then(onFulfilled, onRejected) {
|
|
966
|
+
return this.execute().then(onFulfilled, onRejected);
|
|
967
|
+
}
|
|
968
|
+
};
|
|
969
|
+
});
|
|
970
|
+
|
|
971
|
+
// ../../../../node_modules/drizzle-orm/utils.js
|
|
972
|
+
function mapResultRow(columns, row, joinsNotNullableMap) {
|
|
973
|
+
const nullifyMap = {};
|
|
974
|
+
const result = columns.reduce((result2, { path, field }, columnIndex) => {
|
|
975
|
+
let decoder;
|
|
976
|
+
if (is(field, Column)) {
|
|
977
|
+
decoder = field;
|
|
978
|
+
} else if (is(field, SQL)) {
|
|
979
|
+
decoder = field.decoder;
|
|
980
|
+
} else if (is(field, Subquery)) {
|
|
981
|
+
decoder = field._.sql.decoder;
|
|
982
|
+
} else {
|
|
983
|
+
decoder = field.sql.decoder;
|
|
984
|
+
}
|
|
985
|
+
let node = result2;
|
|
986
|
+
for (const [pathChunkIndex, pathChunk] of path.entries()) {
|
|
987
|
+
if (pathChunkIndex < path.length - 1) {
|
|
988
|
+
if (!(pathChunk in node)) {
|
|
989
|
+
node[pathChunk] = {};
|
|
990
|
+
}
|
|
991
|
+
node = node[pathChunk];
|
|
992
|
+
} else {
|
|
993
|
+
const rawValue = row[columnIndex];
|
|
994
|
+
const value = node[pathChunk] = rawValue === null ? null : decoder.mapFromDriverValue(rawValue);
|
|
995
|
+
if (joinsNotNullableMap && is(field, Column) && path.length === 2) {
|
|
996
|
+
const objectName = path[0];
|
|
997
|
+
if (!(objectName in nullifyMap)) {
|
|
998
|
+
nullifyMap[objectName] = value === null ? getTableName(field.table) : false;
|
|
999
|
+
} else if (typeof nullifyMap[objectName] === "string" && nullifyMap[objectName] !== getTableName(field.table)) {
|
|
1000
|
+
nullifyMap[objectName] = false;
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
return result2;
|
|
1006
|
+
}, {});
|
|
1007
|
+
if (joinsNotNullableMap && Object.keys(nullifyMap).length > 0) {
|
|
1008
|
+
for (const [objectName, tableName] of Object.entries(nullifyMap)) {
|
|
1009
|
+
if (typeof tableName === "string" && !joinsNotNullableMap[tableName]) {
|
|
1010
|
+
result[objectName] = null;
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
return result;
|
|
1015
|
+
}
|
|
1016
|
+
function orderSelectedFields(fields, pathPrefix) {
|
|
1017
|
+
return Object.entries(fields).reduce((result, [name2, field]) => {
|
|
1018
|
+
if (typeof name2 !== "string") {
|
|
1019
|
+
return result;
|
|
1020
|
+
}
|
|
1021
|
+
const newPath = pathPrefix ? [...pathPrefix, name2] : [name2];
|
|
1022
|
+
if (is(field, Column) || is(field, SQL) || is(field, SQL.Aliased) || is(field, Subquery)) {
|
|
1023
|
+
result.push({ path: newPath, field });
|
|
1024
|
+
} else if (is(field, Table)) {
|
|
1025
|
+
result.push(...orderSelectedFields(field[Table.Symbol.Columns], newPath));
|
|
1026
|
+
} else {
|
|
1027
|
+
result.push(...orderSelectedFields(field, newPath));
|
|
1028
|
+
}
|
|
1029
|
+
return result;
|
|
1030
|
+
}, []);
|
|
1031
|
+
}
|
|
1032
|
+
function haveSameKeys(left, right) {
|
|
1033
|
+
const leftKeys = Object.keys(left);
|
|
1034
|
+
const rightKeys = Object.keys(right);
|
|
1035
|
+
if (leftKeys.length !== rightKeys.length) {
|
|
1036
|
+
return false;
|
|
1037
|
+
}
|
|
1038
|
+
for (const [index, key] of leftKeys.entries()) {
|
|
1039
|
+
if (key !== rightKeys[index]) {
|
|
1040
|
+
return false;
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
return true;
|
|
1044
|
+
}
|
|
1045
|
+
function mapUpdateSet(table, values) {
|
|
1046
|
+
const entries = Object.entries(values).filter(([, value]) => value !== undefined).map(([key, value]) => {
|
|
1047
|
+
if (is(value, SQL) || is(value, Column)) {
|
|
1048
|
+
return [key, value];
|
|
1049
|
+
} else {
|
|
1050
|
+
return [key, new Param(value, table[Table.Symbol.Columns][key])];
|
|
1051
|
+
}
|
|
1052
|
+
});
|
|
1053
|
+
if (entries.length === 0) {
|
|
1054
|
+
throw new Error("No values to set");
|
|
1055
|
+
}
|
|
1056
|
+
return Object.fromEntries(entries);
|
|
1057
|
+
}
|
|
1058
|
+
function applyMixins(baseClass, extendedClasses) {
|
|
1059
|
+
for (const extendedClass of extendedClasses) {
|
|
1060
|
+
for (const name2 of Object.getOwnPropertyNames(extendedClass.prototype)) {
|
|
1061
|
+
if (name2 === "constructor")
|
|
1062
|
+
continue;
|
|
1063
|
+
Object.defineProperty(baseClass.prototype, name2, Object.getOwnPropertyDescriptor(extendedClass.prototype, name2) || /* @__PURE__ */ Object.create(null));
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
function getTableColumns(table) {
|
|
1068
|
+
return table[Table.Symbol.Columns];
|
|
1069
|
+
}
|
|
1070
|
+
function getViewSelectedFields(view) {
|
|
1071
|
+
return view[ViewBaseConfig].selectedFields;
|
|
1072
|
+
}
|
|
1073
|
+
function getTableLikeName(table) {
|
|
1074
|
+
return is(table, Subquery) ? table._.alias : is(table, View) ? table[ViewBaseConfig].name : is(table, SQL) ? undefined : table[Table.Symbol.IsAlias] ? table[Table.Symbol.Name] : table[Table.Symbol.BaseName];
|
|
1075
|
+
}
|
|
1076
|
+
function getColumnNameAndConfig(a, b) {
|
|
1077
|
+
return {
|
|
1078
|
+
name: typeof a === "string" && a.length > 0 ? a : "",
|
|
1079
|
+
config: typeof a === "object" ? a : b
|
|
1080
|
+
};
|
|
1081
|
+
}
|
|
1082
|
+
function isConfig(data) {
|
|
1083
|
+
if (typeof data !== "object" || data === null)
|
|
1084
|
+
return false;
|
|
1085
|
+
if (data.constructor.name !== "Object")
|
|
1086
|
+
return false;
|
|
1087
|
+
if ("logger" in data) {
|
|
1088
|
+
const type = typeof data["logger"];
|
|
1089
|
+
if (type !== "boolean" && (type !== "object" || typeof data["logger"]["logQuery"] !== "function") && type !== "undefined")
|
|
1090
|
+
return false;
|
|
1091
|
+
return true;
|
|
1092
|
+
}
|
|
1093
|
+
if ("schema" in data) {
|
|
1094
|
+
const type = typeof data["schema"];
|
|
1095
|
+
if (type !== "object" && type !== "undefined")
|
|
1096
|
+
return false;
|
|
1097
|
+
return true;
|
|
1098
|
+
}
|
|
1099
|
+
if ("casing" in data) {
|
|
1100
|
+
const type = typeof data["casing"];
|
|
1101
|
+
if (type !== "string" && type !== "undefined")
|
|
1102
|
+
return false;
|
|
1103
|
+
return true;
|
|
1104
|
+
}
|
|
1105
|
+
if ("mode" in data) {
|
|
1106
|
+
if (data["mode"] !== "default" || data["mode"] !== "planetscale" || data["mode"] !== undefined)
|
|
1107
|
+
return false;
|
|
1108
|
+
return true;
|
|
1109
|
+
}
|
|
1110
|
+
if ("connection" in data) {
|
|
1111
|
+
const type = typeof data["connection"];
|
|
1112
|
+
if (type !== "string" && type !== "object" && type !== "undefined")
|
|
1113
|
+
return false;
|
|
1114
|
+
return true;
|
|
1115
|
+
}
|
|
1116
|
+
if ("client" in data) {
|
|
1117
|
+
const type = typeof data["client"];
|
|
1118
|
+
if (type !== "object" && type !== "function" && type !== "undefined")
|
|
1119
|
+
return false;
|
|
1120
|
+
return true;
|
|
1121
|
+
}
|
|
1122
|
+
if (Object.keys(data).length === 0)
|
|
1123
|
+
return true;
|
|
1124
|
+
return false;
|
|
1125
|
+
}
|
|
1126
|
+
var textDecoder;
|
|
1127
|
+
var init_utils = __esm(() => {
|
|
1128
|
+
init_column();
|
|
1129
|
+
init_entity();
|
|
1130
|
+
init_sql();
|
|
1131
|
+
init_subquery();
|
|
1132
|
+
init_table();
|
|
1133
|
+
init_view_common();
|
|
1134
|
+
textDecoder = typeof TextDecoder === "undefined" ? null : new TextDecoder;
|
|
1135
|
+
});
|
|
1136
|
+
|
|
1137
|
+
// ../../../../node_modules/drizzle-orm/pg-core/table.js
|
|
1138
|
+
var InlineForeignKeys, EnableRLS, PgTable;
|
|
1139
|
+
var init_table2 = __esm(() => {
|
|
1140
|
+
init_entity();
|
|
1141
|
+
init_table();
|
|
1142
|
+
InlineForeignKeys = Symbol.for("drizzle:PgInlineForeignKeys");
|
|
1143
|
+
EnableRLS = Symbol.for("drizzle:EnableRLS");
|
|
1144
|
+
PgTable = class PgTable extends Table {
|
|
1145
|
+
static [entityKind] = "PgTable";
|
|
1146
|
+
static Symbol = Object.assign({}, Table.Symbol, {
|
|
1147
|
+
InlineForeignKeys,
|
|
1148
|
+
EnableRLS
|
|
1149
|
+
});
|
|
1150
|
+
[InlineForeignKeys] = [];
|
|
1151
|
+
[EnableRLS] = false;
|
|
1152
|
+
[Table.Symbol.ExtraConfigBuilder] = undefined;
|
|
1153
|
+
[Table.Symbol.ExtraConfigColumns] = {};
|
|
1154
|
+
};
|
|
1155
|
+
});
|
|
1156
|
+
|
|
1157
|
+
// ../../../../node_modules/drizzle-orm/pg-core/primary-keys.js
|
|
1158
|
+
var PrimaryKeyBuilder, PrimaryKey;
|
|
1159
|
+
var init_primary_keys = __esm(() => {
|
|
1160
|
+
init_entity();
|
|
1161
|
+
init_table2();
|
|
1162
|
+
PrimaryKeyBuilder = class PrimaryKeyBuilder {
|
|
1163
|
+
static [entityKind] = "PgPrimaryKeyBuilder";
|
|
1164
|
+
columns;
|
|
1165
|
+
name;
|
|
1166
|
+
constructor(columns, name2) {
|
|
1167
|
+
this.columns = columns;
|
|
1168
|
+
this.name = name2;
|
|
1169
|
+
}
|
|
1170
|
+
build(table) {
|
|
1171
|
+
return new PrimaryKey(table, this.columns, this.name);
|
|
1172
|
+
}
|
|
1173
|
+
};
|
|
1174
|
+
PrimaryKey = class PrimaryKey {
|
|
1175
|
+
constructor(table, columns, name2) {
|
|
1176
|
+
this.table = table;
|
|
1177
|
+
this.columns = columns;
|
|
1178
|
+
this.name = name2;
|
|
1179
|
+
}
|
|
1180
|
+
static [entityKind] = "PgPrimaryKey";
|
|
1181
|
+
columns;
|
|
1182
|
+
name;
|
|
1183
|
+
getName() {
|
|
1184
|
+
return this.name ?? `${this.table[PgTable.Symbol.Name]}_${this.columns.map((column) => column.name).join("_")}_pk`;
|
|
1185
|
+
}
|
|
1186
|
+
};
|
|
1187
|
+
});
|
|
1188
|
+
|
|
1189
|
+
// ../../../../node_modules/drizzle-orm/sql/expressions/conditions.js
|
|
1190
|
+
function bindIfParam(value, column) {
|
|
1191
|
+
if (isDriverValueEncoder(column) && !isSQLWrapper(value) && !is(value, Param) && !is(value, Placeholder) && !is(value, Column) && !is(value, Table) && !is(value, View)) {
|
|
1192
|
+
return new Param(value, column);
|
|
1193
|
+
}
|
|
1194
|
+
return value;
|
|
1195
|
+
}
|
|
1196
|
+
function and(...unfilteredConditions) {
|
|
1197
|
+
const conditions = unfilteredConditions.filter((c) => c !== undefined);
|
|
1198
|
+
if (conditions.length === 0) {
|
|
1199
|
+
return;
|
|
1200
|
+
}
|
|
1201
|
+
if (conditions.length === 1) {
|
|
1202
|
+
return new SQL(conditions);
|
|
1203
|
+
}
|
|
1204
|
+
return new SQL([
|
|
1205
|
+
new StringChunk("("),
|
|
1206
|
+
sql.join(conditions, new StringChunk(" and ")),
|
|
1207
|
+
new StringChunk(")")
|
|
1208
|
+
]);
|
|
1209
|
+
}
|
|
1210
|
+
function or(...unfilteredConditions) {
|
|
1211
|
+
const conditions = unfilteredConditions.filter((c) => c !== undefined);
|
|
1212
|
+
if (conditions.length === 0) {
|
|
1213
|
+
return;
|
|
1214
|
+
}
|
|
1215
|
+
if (conditions.length === 1) {
|
|
1216
|
+
return new SQL(conditions);
|
|
1217
|
+
}
|
|
1218
|
+
return new SQL([
|
|
1219
|
+
new StringChunk("("),
|
|
1220
|
+
sql.join(conditions, new StringChunk(" or ")),
|
|
1221
|
+
new StringChunk(")")
|
|
1222
|
+
]);
|
|
1223
|
+
}
|
|
1224
|
+
function not(condition) {
|
|
1225
|
+
return sql`not ${condition}`;
|
|
1226
|
+
}
|
|
1227
|
+
function inArray(column, values) {
|
|
1228
|
+
if (Array.isArray(values)) {
|
|
1229
|
+
if (values.length === 0) {
|
|
1230
|
+
return sql`false`;
|
|
1231
|
+
}
|
|
1232
|
+
return sql`${column} in ${values.map((v) => bindIfParam(v, column))}`;
|
|
1233
|
+
}
|
|
1234
|
+
return sql`${column} in ${bindIfParam(values, column)}`;
|
|
1235
|
+
}
|
|
1236
|
+
function notInArray(column, values) {
|
|
1237
|
+
if (Array.isArray(values)) {
|
|
1238
|
+
if (values.length === 0) {
|
|
1239
|
+
return sql`true`;
|
|
1240
|
+
}
|
|
1241
|
+
return sql`${column} not in ${values.map((v) => bindIfParam(v, column))}`;
|
|
1242
|
+
}
|
|
1243
|
+
return sql`${column} not in ${bindIfParam(values, column)}`;
|
|
1244
|
+
}
|
|
1245
|
+
function isNull(value) {
|
|
1246
|
+
return sql`${value} is null`;
|
|
1247
|
+
}
|
|
1248
|
+
function isNotNull(value) {
|
|
1249
|
+
return sql`${value} is not null`;
|
|
1250
|
+
}
|
|
1251
|
+
function exists(subquery) {
|
|
1252
|
+
return sql`exists ${subquery}`;
|
|
1253
|
+
}
|
|
1254
|
+
function notExists(subquery) {
|
|
1255
|
+
return sql`not exists ${subquery}`;
|
|
1256
|
+
}
|
|
1257
|
+
function between(column, min, max) {
|
|
1258
|
+
return sql`${column} between ${bindIfParam(min, column)} and ${bindIfParam(max, column)}`;
|
|
1259
|
+
}
|
|
1260
|
+
function notBetween(column, min, max) {
|
|
1261
|
+
return sql`${column} not between ${bindIfParam(min, column)} and ${bindIfParam(max, column)}`;
|
|
1262
|
+
}
|
|
1263
|
+
function like(column, value) {
|
|
1264
|
+
return sql`${column} like ${value}`;
|
|
1265
|
+
}
|
|
1266
|
+
function notLike(column, value) {
|
|
1267
|
+
return sql`${column} not like ${value}`;
|
|
1268
|
+
}
|
|
1269
|
+
function ilike(column, value) {
|
|
1270
|
+
return sql`${column} ilike ${value}`;
|
|
1271
|
+
}
|
|
1272
|
+
function notIlike(column, value) {
|
|
1273
|
+
return sql`${column} not ilike ${value}`;
|
|
1274
|
+
}
|
|
1275
|
+
function arrayContains(column, values) {
|
|
1276
|
+
if (Array.isArray(values)) {
|
|
1277
|
+
if (values.length === 0) {
|
|
1278
|
+
throw new Error("arrayContains requires at least one value");
|
|
1279
|
+
}
|
|
1280
|
+
const array = sql`${bindIfParam(values, column)}`;
|
|
1281
|
+
return sql`${column} @> ${array}`;
|
|
1282
|
+
}
|
|
1283
|
+
return sql`${column} @> ${bindIfParam(values, column)}`;
|
|
1284
|
+
}
|
|
1285
|
+
function arrayContained(column, values) {
|
|
1286
|
+
if (Array.isArray(values)) {
|
|
1287
|
+
if (values.length === 0) {
|
|
1288
|
+
throw new Error("arrayContained requires at least one value");
|
|
1289
|
+
}
|
|
1290
|
+
const array = sql`${bindIfParam(values, column)}`;
|
|
1291
|
+
return sql`${column} <@ ${array}`;
|
|
1292
|
+
}
|
|
1293
|
+
return sql`${column} <@ ${bindIfParam(values, column)}`;
|
|
1294
|
+
}
|
|
1295
|
+
function arrayOverlaps(column, values) {
|
|
1296
|
+
if (Array.isArray(values)) {
|
|
1297
|
+
if (values.length === 0) {
|
|
1298
|
+
throw new Error("arrayOverlaps requires at least one value");
|
|
1299
|
+
}
|
|
1300
|
+
const array = sql`${bindIfParam(values, column)}`;
|
|
1301
|
+
return sql`${column} && ${array}`;
|
|
1302
|
+
}
|
|
1303
|
+
return sql`${column} && ${bindIfParam(values, column)}`;
|
|
1304
|
+
}
|
|
1305
|
+
var eq = (left, right) => {
|
|
1306
|
+
return sql`${left} = ${bindIfParam(right, left)}`;
|
|
1307
|
+
}, ne = (left, right) => {
|
|
1308
|
+
return sql`${left} <> ${bindIfParam(right, left)}`;
|
|
1309
|
+
}, gt = (left, right) => {
|
|
1310
|
+
return sql`${left} > ${bindIfParam(right, left)}`;
|
|
1311
|
+
}, gte = (left, right) => {
|
|
1312
|
+
return sql`${left} >= ${bindIfParam(right, left)}`;
|
|
1313
|
+
}, lt = (left, right) => {
|
|
1314
|
+
return sql`${left} < ${bindIfParam(right, left)}`;
|
|
1315
|
+
}, lte = (left, right) => {
|
|
1316
|
+
return sql`${left} <= ${bindIfParam(right, left)}`;
|
|
1317
|
+
};
|
|
1318
|
+
var init_conditions = __esm(() => {
|
|
1319
|
+
init_column();
|
|
1320
|
+
init_entity();
|
|
1321
|
+
init_table();
|
|
1322
|
+
init_sql();
|
|
1323
|
+
});
|
|
1324
|
+
|
|
1325
|
+
// ../../../../node_modules/drizzle-orm/sql/expressions/select.js
|
|
1326
|
+
function asc(column) {
|
|
1327
|
+
return sql`${column} asc`;
|
|
1328
|
+
}
|
|
1329
|
+
function desc(column) {
|
|
1330
|
+
return sql`${column} desc`;
|
|
1331
|
+
}
|
|
1332
|
+
var init_select = __esm(() => {
|
|
1333
|
+
init_sql();
|
|
1334
|
+
});
|
|
1335
|
+
|
|
1336
|
+
// ../../../../node_modules/drizzle-orm/sql/expressions/index.js
|
|
1337
|
+
var init_expressions = __esm(() => {
|
|
1338
|
+
init_conditions();
|
|
1339
|
+
init_select();
|
|
1340
|
+
});
|
|
1341
|
+
|
|
1342
|
+
// ../../../../node_modules/drizzle-orm/relations.js
|
|
1343
|
+
function getOperators() {
|
|
1344
|
+
return {
|
|
1345
|
+
and,
|
|
1346
|
+
between,
|
|
1347
|
+
eq,
|
|
1348
|
+
exists,
|
|
1349
|
+
gt,
|
|
1350
|
+
gte,
|
|
1351
|
+
ilike,
|
|
1352
|
+
inArray,
|
|
1353
|
+
isNull,
|
|
1354
|
+
isNotNull,
|
|
1355
|
+
like,
|
|
1356
|
+
lt,
|
|
1357
|
+
lte,
|
|
1358
|
+
ne,
|
|
1359
|
+
not,
|
|
1360
|
+
notBetween,
|
|
1361
|
+
notExists,
|
|
1362
|
+
notLike,
|
|
1363
|
+
notIlike,
|
|
1364
|
+
notInArray,
|
|
1365
|
+
or,
|
|
1366
|
+
sql
|
|
1367
|
+
};
|
|
1368
|
+
}
|
|
1369
|
+
function getOrderByOperators() {
|
|
1370
|
+
return {
|
|
1371
|
+
sql,
|
|
1372
|
+
asc,
|
|
1373
|
+
desc
|
|
1374
|
+
};
|
|
1375
|
+
}
|
|
1376
|
+
function extractTablesRelationalConfig(schema, configHelpers) {
|
|
1377
|
+
if (Object.keys(schema).length === 1 && "default" in schema && !is(schema["default"], Table)) {
|
|
1378
|
+
schema = schema["default"];
|
|
1379
|
+
}
|
|
1380
|
+
const tableNamesMap = {};
|
|
1381
|
+
const relationsBuffer = {};
|
|
1382
|
+
const tablesConfig = {};
|
|
1383
|
+
for (const [key, value] of Object.entries(schema)) {
|
|
1384
|
+
if (is(value, Table)) {
|
|
1385
|
+
const dbName = getTableUniqueName(value);
|
|
1386
|
+
const bufferedRelations = relationsBuffer[dbName];
|
|
1387
|
+
tableNamesMap[dbName] = key;
|
|
1388
|
+
tablesConfig[key] = {
|
|
1389
|
+
tsName: key,
|
|
1390
|
+
dbName: value[Table.Symbol.Name],
|
|
1391
|
+
schema: value[Table.Symbol.Schema],
|
|
1392
|
+
columns: value[Table.Symbol.Columns],
|
|
1393
|
+
relations: bufferedRelations?.relations ?? {},
|
|
1394
|
+
primaryKey: bufferedRelations?.primaryKey ?? []
|
|
1395
|
+
};
|
|
1396
|
+
for (const column of Object.values(value[Table.Symbol.Columns])) {
|
|
1397
|
+
if (column.primary) {
|
|
1398
|
+
tablesConfig[key].primaryKey.push(column);
|
|
1399
|
+
}
|
|
1400
|
+
}
|
|
1401
|
+
const extraConfig = value[Table.Symbol.ExtraConfigBuilder]?.(value[Table.Symbol.ExtraConfigColumns]);
|
|
1402
|
+
if (extraConfig) {
|
|
1403
|
+
for (const configEntry of Object.values(extraConfig)) {
|
|
1404
|
+
if (is(configEntry, PrimaryKeyBuilder)) {
|
|
1405
|
+
tablesConfig[key].primaryKey.push(...configEntry.columns);
|
|
1406
|
+
}
|
|
1407
|
+
}
|
|
1408
|
+
}
|
|
1409
|
+
} else if (is(value, Relations)) {
|
|
1410
|
+
const dbName = getTableUniqueName(value.table);
|
|
1411
|
+
const tableName = tableNamesMap[dbName];
|
|
1412
|
+
const relations2 = value.config(configHelpers(value.table));
|
|
1413
|
+
let primaryKey;
|
|
1414
|
+
for (const [relationName, relation] of Object.entries(relations2)) {
|
|
1415
|
+
if (tableName) {
|
|
1416
|
+
const tableConfig = tablesConfig[tableName];
|
|
1417
|
+
tableConfig.relations[relationName] = relation;
|
|
1418
|
+
if (primaryKey) {
|
|
1419
|
+
tableConfig.primaryKey.push(...primaryKey);
|
|
1420
|
+
}
|
|
1421
|
+
} else {
|
|
1422
|
+
if (!(dbName in relationsBuffer)) {
|
|
1423
|
+
relationsBuffer[dbName] = {
|
|
1424
|
+
relations: {},
|
|
1425
|
+
primaryKey
|
|
1426
|
+
};
|
|
1427
|
+
}
|
|
1428
|
+
relationsBuffer[dbName].relations[relationName] = relation;
|
|
1429
|
+
}
|
|
1430
|
+
}
|
|
1431
|
+
}
|
|
1432
|
+
}
|
|
1433
|
+
return { tables: tablesConfig, tableNamesMap };
|
|
1434
|
+
}
|
|
1435
|
+
function relations(table, relations2) {
|
|
1436
|
+
return new Relations(table, (helpers) => Object.fromEntries(Object.entries(relations2(helpers)).map(([key, value]) => [
|
|
1437
|
+
key,
|
|
1438
|
+
value.withFieldName(key)
|
|
1439
|
+
])));
|
|
1440
|
+
}
|
|
1441
|
+
function createOne(sourceTable) {
|
|
1442
|
+
return function one(table, config) {
|
|
1443
|
+
return new One(sourceTable, table, config, config?.fields.reduce((res, f) => res && f.notNull, true) ?? false);
|
|
1444
|
+
};
|
|
1445
|
+
}
|
|
1446
|
+
function createMany(sourceTable) {
|
|
1447
|
+
return function many(referencedTable, config) {
|
|
1448
|
+
return new Many(sourceTable, referencedTable, config);
|
|
1449
|
+
};
|
|
1450
|
+
}
|
|
1451
|
+
function normalizeRelation(schema, tableNamesMap, relation) {
|
|
1452
|
+
if (is(relation, One) && relation.config) {
|
|
1453
|
+
return {
|
|
1454
|
+
fields: relation.config.fields,
|
|
1455
|
+
references: relation.config.references
|
|
1456
|
+
};
|
|
1457
|
+
}
|
|
1458
|
+
const referencedTableTsName = tableNamesMap[getTableUniqueName(relation.referencedTable)];
|
|
1459
|
+
if (!referencedTableTsName) {
|
|
1460
|
+
throw new Error(`Table "${relation.referencedTable[Table.Symbol.Name]}" not found in schema`);
|
|
1461
|
+
}
|
|
1462
|
+
const referencedTableConfig = schema[referencedTableTsName];
|
|
1463
|
+
if (!referencedTableConfig) {
|
|
1464
|
+
throw new Error(`Table "${referencedTableTsName}" not found in schema`);
|
|
1465
|
+
}
|
|
1466
|
+
const sourceTable = relation.sourceTable;
|
|
1467
|
+
const sourceTableTsName = tableNamesMap[getTableUniqueName(sourceTable)];
|
|
1468
|
+
if (!sourceTableTsName) {
|
|
1469
|
+
throw new Error(`Table "${sourceTable[Table.Symbol.Name]}" not found in schema`);
|
|
1470
|
+
}
|
|
1471
|
+
const reverseRelations = [];
|
|
1472
|
+
for (const referencedTableRelation of Object.values(referencedTableConfig.relations)) {
|
|
1473
|
+
if (relation.relationName && relation !== referencedTableRelation && referencedTableRelation.relationName === relation.relationName || !relation.relationName && referencedTableRelation.referencedTable === relation.sourceTable) {
|
|
1474
|
+
reverseRelations.push(referencedTableRelation);
|
|
1475
|
+
}
|
|
1476
|
+
}
|
|
1477
|
+
if (reverseRelations.length > 1) {
|
|
1478
|
+
throw relation.relationName ? new Error(`There are multiple relations with name "${relation.relationName}" in table "${referencedTableTsName}"`) : new Error(`There are multiple relations between "${referencedTableTsName}" and "${relation.sourceTable[Table.Symbol.Name]}". Please specify relation name`);
|
|
1479
|
+
}
|
|
1480
|
+
if (reverseRelations[0] && is(reverseRelations[0], One) && reverseRelations[0].config) {
|
|
1481
|
+
return {
|
|
1482
|
+
fields: reverseRelations[0].config.references,
|
|
1483
|
+
references: reverseRelations[0].config.fields
|
|
1484
|
+
};
|
|
1485
|
+
}
|
|
1486
|
+
throw new Error(`There is not enough information to infer relation "${sourceTableTsName}.${relation.fieldName}"`);
|
|
1487
|
+
}
|
|
1488
|
+
function createTableRelationsHelpers(sourceTable) {
|
|
1489
|
+
return {
|
|
1490
|
+
one: createOne(sourceTable),
|
|
1491
|
+
many: createMany(sourceTable)
|
|
1492
|
+
};
|
|
1493
|
+
}
|
|
1494
|
+
function mapRelationalRow(tablesConfig, tableConfig, row, buildQueryResultSelection, mapColumnValue = (value) => value) {
|
|
1495
|
+
const result = {};
|
|
1496
|
+
for (const [
|
|
1497
|
+
selectionItemIndex,
|
|
1498
|
+
selectionItem
|
|
1499
|
+
] of buildQueryResultSelection.entries()) {
|
|
1500
|
+
if (selectionItem.isJson) {
|
|
1501
|
+
const relation = tableConfig.relations[selectionItem.tsKey];
|
|
1502
|
+
const rawSubRows = row[selectionItemIndex];
|
|
1503
|
+
const subRows = typeof rawSubRows === "string" ? JSON.parse(rawSubRows) : rawSubRows;
|
|
1504
|
+
result[selectionItem.tsKey] = is(relation, One) ? subRows && mapRelationalRow(tablesConfig, tablesConfig[selectionItem.relationTableTsKey], subRows, selectionItem.selection, mapColumnValue) : subRows.map((subRow) => mapRelationalRow(tablesConfig, tablesConfig[selectionItem.relationTableTsKey], subRow, selectionItem.selection, mapColumnValue));
|
|
1505
|
+
} else {
|
|
1506
|
+
const value = mapColumnValue(row[selectionItemIndex]);
|
|
1507
|
+
const field = selectionItem.field;
|
|
1508
|
+
let decoder;
|
|
1509
|
+
if (is(field, Column)) {
|
|
1510
|
+
decoder = field;
|
|
1511
|
+
} else if (is(field, SQL)) {
|
|
1512
|
+
decoder = field.decoder;
|
|
1513
|
+
} else {
|
|
1514
|
+
decoder = field.sql.decoder;
|
|
1515
|
+
}
|
|
1516
|
+
result[selectionItem.tsKey] = value === null ? null : decoder.mapFromDriverValue(value);
|
|
1517
|
+
}
|
|
1518
|
+
}
|
|
1519
|
+
return result;
|
|
1520
|
+
}
|
|
1521
|
+
var Relation, Relations, One, Many;
|
|
1522
|
+
var init_relations = __esm(() => {
|
|
1523
|
+
init_table();
|
|
1524
|
+
init_column();
|
|
1525
|
+
init_entity();
|
|
1526
|
+
init_primary_keys();
|
|
1527
|
+
init_expressions();
|
|
1528
|
+
init_sql();
|
|
1529
|
+
Relation = class Relation {
|
|
1530
|
+
constructor(sourceTable, referencedTable, relationName) {
|
|
1531
|
+
this.sourceTable = sourceTable;
|
|
1532
|
+
this.referencedTable = referencedTable;
|
|
1533
|
+
this.relationName = relationName;
|
|
1534
|
+
this.referencedTableName = referencedTable[Table.Symbol.Name];
|
|
1535
|
+
}
|
|
1536
|
+
static [entityKind] = "Relation";
|
|
1537
|
+
referencedTableName;
|
|
1538
|
+
fieldName;
|
|
1539
|
+
};
|
|
1540
|
+
Relations = class Relations {
|
|
1541
|
+
constructor(table, config) {
|
|
1542
|
+
this.table = table;
|
|
1543
|
+
this.config = config;
|
|
1544
|
+
}
|
|
1545
|
+
static [entityKind] = "Relations";
|
|
1546
|
+
};
|
|
1547
|
+
One = class One extends Relation {
|
|
1548
|
+
constructor(sourceTable, referencedTable, config, isNullable) {
|
|
1549
|
+
super(sourceTable, referencedTable, config?.relationName);
|
|
1550
|
+
this.config = config;
|
|
1551
|
+
this.isNullable = isNullable;
|
|
1552
|
+
}
|
|
1553
|
+
static [entityKind] = "One";
|
|
1554
|
+
withFieldName(fieldName) {
|
|
1555
|
+
const relation = new One(this.sourceTable, this.referencedTable, this.config, this.isNullable);
|
|
1556
|
+
relation.fieldName = fieldName;
|
|
1557
|
+
return relation;
|
|
1558
|
+
}
|
|
1559
|
+
};
|
|
1560
|
+
Many = class Many extends Relation {
|
|
1561
|
+
constructor(sourceTable, referencedTable, config) {
|
|
1562
|
+
super(sourceTable, referencedTable, config?.relationName);
|
|
1563
|
+
this.config = config;
|
|
1564
|
+
}
|
|
1565
|
+
static [entityKind] = "Many";
|
|
1566
|
+
withFieldName(fieldName) {
|
|
1567
|
+
const relation = new Many(this.sourceTable, this.referencedTable, this.config);
|
|
1568
|
+
relation.fieldName = fieldName;
|
|
1569
|
+
return relation;
|
|
1570
|
+
}
|
|
1571
|
+
};
|
|
1572
|
+
});
|
|
1573
|
+
|
|
1574
|
+
// ../../../../node_modules/drizzle-orm/sql/functions/aggregate.js
|
|
1575
|
+
function count(expression) {
|
|
1576
|
+
return sql`count(${expression || sql.raw("*")})`.mapWith(Number);
|
|
1577
|
+
}
|
|
1578
|
+
function countDistinct(expression) {
|
|
1579
|
+
return sql`count(distinct ${expression})`.mapWith(Number);
|
|
1580
|
+
}
|
|
1581
|
+
function avg(expression) {
|
|
1582
|
+
return sql`avg(${expression})`.mapWith(String);
|
|
1583
|
+
}
|
|
1584
|
+
function avgDistinct(expression) {
|
|
1585
|
+
return sql`avg(distinct ${expression})`.mapWith(String);
|
|
1586
|
+
}
|
|
1587
|
+
function sum(expression) {
|
|
1588
|
+
return sql`sum(${expression})`.mapWith(String);
|
|
1589
|
+
}
|
|
1590
|
+
function sumDistinct(expression) {
|
|
1591
|
+
return sql`sum(distinct ${expression})`.mapWith(String);
|
|
1592
|
+
}
|
|
1593
|
+
function max(expression) {
|
|
1594
|
+
return sql`max(${expression})`.mapWith(is(expression, Column) ? expression : String);
|
|
1595
|
+
}
|
|
1596
|
+
function min(expression) {
|
|
1597
|
+
return sql`min(${expression})`.mapWith(is(expression, Column) ? expression : String);
|
|
1598
|
+
}
|
|
1599
|
+
var init_aggregate = __esm(() => {
|
|
1600
|
+
init_column();
|
|
1601
|
+
init_entity();
|
|
1602
|
+
init_sql();
|
|
1603
|
+
});
|
|
1604
|
+
|
|
1605
|
+
// ../../../../node_modules/drizzle-orm/sql/functions/vector.js
|
|
1606
|
+
function toSql(value) {
|
|
1607
|
+
return JSON.stringify(value);
|
|
1608
|
+
}
|
|
1609
|
+
function l2Distance(column, value) {
|
|
1610
|
+
if (Array.isArray(value)) {
|
|
1611
|
+
return sql`${column} <-> ${toSql(value)}`;
|
|
1612
|
+
}
|
|
1613
|
+
return sql`${column} <-> ${value}`;
|
|
1614
|
+
}
|
|
1615
|
+
function l1Distance(column, value) {
|
|
1616
|
+
if (Array.isArray(value)) {
|
|
1617
|
+
return sql`${column} <+> ${toSql(value)}`;
|
|
1618
|
+
}
|
|
1619
|
+
return sql`${column} <+> ${value}`;
|
|
1620
|
+
}
|
|
1621
|
+
function innerProduct(column, value) {
|
|
1622
|
+
if (Array.isArray(value)) {
|
|
1623
|
+
return sql`${column} <#> ${toSql(value)}`;
|
|
1624
|
+
}
|
|
1625
|
+
return sql`${column} <#> ${value}`;
|
|
1626
|
+
}
|
|
1627
|
+
function cosineDistance(column, value) {
|
|
1628
|
+
if (Array.isArray(value)) {
|
|
1629
|
+
return sql`${column} <=> ${toSql(value)}`;
|
|
1630
|
+
}
|
|
1631
|
+
return sql`${column} <=> ${value}`;
|
|
1632
|
+
}
|
|
1633
|
+
function hammingDistance(column, value) {
|
|
1634
|
+
if (Array.isArray(value)) {
|
|
1635
|
+
return sql`${column} <~> ${toSql(value)}`;
|
|
1636
|
+
}
|
|
1637
|
+
return sql`${column} <~> ${value}`;
|
|
1638
|
+
}
|
|
1639
|
+
function jaccardDistance(column, value) {
|
|
1640
|
+
if (Array.isArray(value)) {
|
|
1641
|
+
return sql`${column} <%> ${toSql(value)}`;
|
|
1642
|
+
}
|
|
1643
|
+
return sql`${column} <%> ${value}`;
|
|
1644
|
+
}
|
|
1645
|
+
var init_vector = __esm(() => {
|
|
1646
|
+
init_sql();
|
|
1647
|
+
});
|
|
1648
|
+
|
|
1649
|
+
// ../../../../node_modules/drizzle-orm/sql/functions/index.js
|
|
1650
|
+
var init_functions = __esm(() => {
|
|
1651
|
+
init_aggregate();
|
|
1652
|
+
init_vector();
|
|
1653
|
+
});
|
|
1654
|
+
|
|
1655
|
+
// ../../../../node_modules/drizzle-orm/sql/index.js
|
|
1656
|
+
var init_sql2 = __esm(() => {
|
|
1657
|
+
init_expressions();
|
|
1658
|
+
init_functions();
|
|
1659
|
+
init_sql();
|
|
1660
|
+
});
|
|
1661
|
+
|
|
1662
|
+
// ../../../../node_modules/drizzle-orm/index.js
|
|
1663
|
+
var exports_drizzle_orm = {};
|
|
1664
|
+
__export(exports_drizzle_orm, {
|
|
1665
|
+
textDecoder: () => textDecoder,
|
|
1666
|
+
sumDistinct: () => sumDistinct,
|
|
1667
|
+
sum: () => sum,
|
|
1668
|
+
sql: () => sql,
|
|
1669
|
+
relations: () => relations,
|
|
1670
|
+
placeholder: () => placeholder,
|
|
1671
|
+
param: () => param,
|
|
1672
|
+
orderSelectedFields: () => orderSelectedFields,
|
|
1673
|
+
or: () => or,
|
|
1674
|
+
notLike: () => notLike,
|
|
1675
|
+
notInArray: () => notInArray,
|
|
1676
|
+
notIlike: () => notIlike,
|
|
1677
|
+
notExists: () => notExists,
|
|
1678
|
+
notBetween: () => notBetween,
|
|
1679
|
+
not: () => not,
|
|
1680
|
+
normalizeRelation: () => normalizeRelation,
|
|
1681
|
+
noopMapper: () => noopMapper,
|
|
1682
|
+
noopEncoder: () => noopEncoder,
|
|
1683
|
+
noopDecoder: () => noopDecoder,
|
|
1684
|
+
ne: () => ne,
|
|
1685
|
+
name: () => name,
|
|
1686
|
+
min: () => min,
|
|
1687
|
+
max: () => max,
|
|
1688
|
+
mapUpdateSet: () => mapUpdateSet,
|
|
1689
|
+
mapResultRow: () => mapResultRow,
|
|
1690
|
+
mapRelationalRow: () => mapRelationalRow,
|
|
1691
|
+
mapColumnsInSQLToAlias: () => mapColumnsInSQLToAlias,
|
|
1692
|
+
mapColumnsInAliasedSQLToAlias: () => mapColumnsInAliasedSQLToAlias,
|
|
1693
|
+
lte: () => lte,
|
|
1694
|
+
lt: () => lt,
|
|
1695
|
+
like: () => like,
|
|
1696
|
+
l2Distance: () => l2Distance,
|
|
1697
|
+
l1Distance: () => l1Distance,
|
|
1698
|
+
jaccardDistance: () => jaccardDistance,
|
|
1699
|
+
isView: () => isView,
|
|
1700
|
+
isTable: () => isTable,
|
|
1701
|
+
isSQLWrapper: () => isSQLWrapper,
|
|
1702
|
+
isNull: () => isNull,
|
|
1703
|
+
isNotNull: () => isNotNull,
|
|
1704
|
+
isDriverValueEncoder: () => isDriverValueEncoder,
|
|
1705
|
+
isConfig: () => isConfig,
|
|
1706
|
+
is: () => is,
|
|
1707
|
+
innerProduct: () => innerProduct,
|
|
1708
|
+
inArray: () => inArray,
|
|
1709
|
+
ilike: () => ilike,
|
|
1710
|
+
haveSameKeys: () => haveSameKeys,
|
|
1711
|
+
hasOwnEntityKind: () => hasOwnEntityKind,
|
|
1712
|
+
hammingDistance: () => hammingDistance,
|
|
1713
|
+
gte: () => gte,
|
|
1714
|
+
gt: () => gt,
|
|
1715
|
+
getViewSelectedFields: () => getViewSelectedFields,
|
|
1716
|
+
getViewName: () => getViewName,
|
|
1717
|
+
getTableUniqueName: () => getTableUniqueName,
|
|
1718
|
+
getTableName: () => getTableName,
|
|
1719
|
+
getTableLikeName: () => getTableLikeName,
|
|
1720
|
+
getTableColumns: () => getTableColumns,
|
|
1721
|
+
getOrderByOperators: () => getOrderByOperators,
|
|
1722
|
+
getOperators: () => getOperators,
|
|
1723
|
+
getColumnNameAndConfig: () => getColumnNameAndConfig,
|
|
1724
|
+
fillPlaceholders: () => fillPlaceholders,
|
|
1725
|
+
extractTablesRelationalConfig: () => extractTablesRelationalConfig,
|
|
1726
|
+
exists: () => exists,
|
|
1727
|
+
eq: () => eq,
|
|
1728
|
+
entityKind: () => entityKind,
|
|
1729
|
+
desc: () => desc,
|
|
1730
|
+
createTableRelationsHelpers: () => createTableRelationsHelpers,
|
|
1731
|
+
createOne: () => createOne,
|
|
1732
|
+
createMany: () => createMany,
|
|
1733
|
+
countDistinct: () => countDistinct,
|
|
1734
|
+
count: () => count,
|
|
1735
|
+
cosineDistance: () => cosineDistance,
|
|
1736
|
+
bindIfParam: () => bindIfParam,
|
|
1737
|
+
between: () => between,
|
|
1738
|
+
avgDistinct: () => avgDistinct,
|
|
1739
|
+
avg: () => avg,
|
|
1740
|
+
asc: () => asc,
|
|
1741
|
+
arrayOverlaps: () => arrayOverlaps,
|
|
1742
|
+
arrayContains: () => arrayContains,
|
|
1743
|
+
arrayContained: () => arrayContained,
|
|
1744
|
+
applyMixins: () => applyMixins,
|
|
1745
|
+
and: () => and,
|
|
1746
|
+
aliasedTableColumn: () => aliasedTableColumn,
|
|
1747
|
+
aliasedTable: () => aliasedTable,
|
|
1748
|
+
aliasedRelation: () => aliasedRelation,
|
|
1749
|
+
WithSubquery: () => WithSubquery,
|
|
1750
|
+
ViewBaseConfig: () => ViewBaseConfig,
|
|
1751
|
+
View: () => View,
|
|
1752
|
+
TransactionRollbackError: () => TransactionRollbackError,
|
|
1753
|
+
TableAliasProxyHandler: () => TableAliasProxyHandler,
|
|
1754
|
+
Table: () => Table,
|
|
1755
|
+
Subquery: () => Subquery,
|
|
1756
|
+
StringChunk: () => StringChunk,
|
|
1757
|
+
Schema: () => Schema,
|
|
1758
|
+
SQL: () => SQL,
|
|
1759
|
+
Relations: () => Relations,
|
|
1760
|
+
RelationTableAliasProxyHandler: () => RelationTableAliasProxyHandler,
|
|
1761
|
+
Relation: () => Relation,
|
|
1762
|
+
QueryPromise: () => QueryPromise,
|
|
1763
|
+
Placeholder: () => Placeholder,
|
|
1764
|
+
Param: () => Param,
|
|
1765
|
+
OriginalName: () => OriginalName,
|
|
1766
|
+
One: () => One,
|
|
1767
|
+
NoopLogger: () => NoopLogger,
|
|
1768
|
+
Name: () => Name,
|
|
1769
|
+
Many: () => Many,
|
|
1770
|
+
IsAlias: () => IsAlias,
|
|
1771
|
+
FakePrimitiveParam: () => FakePrimitiveParam,
|
|
1772
|
+
ExtraConfigColumns: () => ExtraConfigColumns,
|
|
1773
|
+
ExtraConfigBuilder: () => ExtraConfigBuilder,
|
|
1774
|
+
DrizzleQueryError: () => DrizzleQueryError,
|
|
1775
|
+
DrizzleError: () => DrizzleError,
|
|
1776
|
+
DefaultLogger: () => DefaultLogger,
|
|
1777
|
+
ConsoleLogWriter: () => ConsoleLogWriter,
|
|
1778
|
+
Columns: () => Columns,
|
|
1779
|
+
ColumnBuilder: () => ColumnBuilder,
|
|
1780
|
+
ColumnAliasProxyHandler: () => ColumnAliasProxyHandler,
|
|
1781
|
+
Column: () => Column,
|
|
1782
|
+
BaseName: () => BaseName
|
|
1783
|
+
});
|
|
1784
|
+
var init_drizzle_orm = __esm(() => {
|
|
1785
|
+
init_alias();
|
|
1786
|
+
init_column_builder();
|
|
1787
|
+
init_column();
|
|
1788
|
+
init_entity();
|
|
1789
|
+
init_errors();
|
|
1790
|
+
init_logger();
|
|
1791
|
+
init_query_promise();
|
|
1792
|
+
init_relations();
|
|
1793
|
+
init_sql2();
|
|
1794
|
+
init_subquery();
|
|
1795
|
+
init_table();
|
|
1796
|
+
init_utils();
|
|
1797
|
+
init_view_common();
|
|
1798
|
+
});
|
|
1799
|
+
|
|
1
1800
|
// index.ts
|
|
2
|
-
import {
|
|
1801
|
+
import {
|
|
1802
|
+
createUniqueUuid
|
|
1803
|
+
} from "@elizaos/core";
|
|
1804
|
+
import crypto from "node:crypto";
|
|
1805
|
+
|
|
1806
|
+
// TrajectoryLoggerService.ts
|
|
1807
|
+
import {
|
|
1808
|
+
logger as logger2,
|
|
1809
|
+
Service,
|
|
1810
|
+
getTrajectoryContext,
|
|
1811
|
+
runWithTrajectoryContext,
|
|
1812
|
+
setTrajectoryContextManager,
|
|
1813
|
+
ModelType
|
|
1814
|
+
} from "@elizaos/core";
|
|
1815
|
+
import { v4 as uuidv4 } from "uuid";
|
|
1816
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
1817
|
+
var trajectoryStorage = new AsyncLocalStorage;
|
|
1818
|
+
setTrajectoryContextManager({
|
|
1819
|
+
run(context, fn) {
|
|
1820
|
+
return trajectoryStorage.run(context, fn);
|
|
1821
|
+
},
|
|
1822
|
+
active() {
|
|
1823
|
+
return trajectoryStorage.getStore();
|
|
1824
|
+
}
|
|
1825
|
+
});
|
|
1826
|
+
function asNumber(value) {
|
|
1827
|
+
if (typeof value === "number" && Number.isFinite(value))
|
|
1828
|
+
return value;
|
|
1829
|
+
if (typeof value === "string") {
|
|
1830
|
+
const parsed = Number(value);
|
|
1831
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
1832
|
+
}
|
|
1833
|
+
return null;
|
|
1834
|
+
}
|
|
1835
|
+
function asString(value) {
|
|
1836
|
+
if (typeof value === "string")
|
|
1837
|
+
return value;
|
|
1838
|
+
if (typeof value === "number" || typeof value === "boolean")
|
|
1839
|
+
return String(value);
|
|
1840
|
+
if (value instanceof Date)
|
|
1841
|
+
return value.toISOString();
|
|
1842
|
+
return null;
|
|
1843
|
+
}
|
|
1844
|
+
function asIsoString(value) {
|
|
1845
|
+
if (value instanceof Date)
|
|
1846
|
+
return value.toISOString();
|
|
1847
|
+
const asText = asString(value);
|
|
1848
|
+
if (!asText)
|
|
1849
|
+
return new Date(0).toISOString();
|
|
1850
|
+
const parsed = new Date(asText);
|
|
1851
|
+
if (Number.isNaN(parsed.getTime()))
|
|
1852
|
+
return new Date(0).toISOString();
|
|
1853
|
+
return parsed.toISOString();
|
|
1854
|
+
}
|
|
1855
|
+
function pickCell(row, ...keys) {
|
|
1856
|
+
for (const key of keys) {
|
|
1857
|
+
if (Object.hasOwn(row, key)) {
|
|
1858
|
+
return row[key];
|
|
1859
|
+
}
|
|
1860
|
+
}
|
|
1861
|
+
return;
|
|
1862
|
+
}
|
|
1863
|
+
function sqlLiteral(v) {
|
|
1864
|
+
if (v === null || v === undefined)
|
|
1865
|
+
return "NULL";
|
|
1866
|
+
if (typeof v === "number")
|
|
1867
|
+
return String(v);
|
|
1868
|
+
if (typeof v === "boolean")
|
|
1869
|
+
return v ? "TRUE" : "FALSE";
|
|
1870
|
+
if (typeof v === "object")
|
|
1871
|
+
return `'${JSON.stringify(v).replace(/'/g, "''")}'`;
|
|
1872
|
+
return `'${String(v).replace(/'/g, "''")}'`;
|
|
1873
|
+
}
|
|
3
1874
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1875
|
+
class TrajectoryLoggerService extends Service {
|
|
1876
|
+
static serviceType = "trajectory_logger";
|
|
1877
|
+
get serviceType() {
|
|
1878
|
+
return TrajectoryLoggerService.serviceType;
|
|
1879
|
+
}
|
|
1880
|
+
capabilityDescription = "Captures and persists LLM calls, provider accesses, and full trajectories for debugging, analysis, and RL training";
|
|
1881
|
+
enabled = true;
|
|
1882
|
+
initialized = false;
|
|
1883
|
+
observationBuffer = [];
|
|
1884
|
+
observationFlushTimer = null;
|
|
1885
|
+
observationFlushInProgress = false;
|
|
1886
|
+
OBSERVATION_BUFFER_THRESHOLD = 5;
|
|
1887
|
+
OBSERVATION_FLUSH_INTERVAL_MS = 10 * 60 * 1000;
|
|
1888
|
+
pushChatExchange(exchange) {
|
|
1889
|
+
this.observationBuffer.push(exchange);
|
|
1890
|
+
if (this.observationBuffer.length >= this.OBSERVATION_BUFFER_THRESHOLD) {
|
|
1891
|
+
this.flushObservationBuffer().catch(() => {});
|
|
1892
|
+
return;
|
|
1893
|
+
}
|
|
1894
|
+
if (this.observationFlushTimer)
|
|
1895
|
+
clearTimeout(this.observationFlushTimer);
|
|
1896
|
+
this.observationFlushTimer = setTimeout(() => {
|
|
1897
|
+
this.flushObservationBuffer().catch(() => {});
|
|
1898
|
+
}, this.OBSERVATION_FLUSH_INTERVAL_MS);
|
|
1899
|
+
}
|
|
1900
|
+
async flushObservationBuffer() {
|
|
1901
|
+
if (this.observationFlushInProgress)
|
|
1902
|
+
return [];
|
|
1903
|
+
this.observationFlushInProgress = true;
|
|
1904
|
+
if (this.observationBuffer.length === 0) {
|
|
1905
|
+
this.observationFlushInProgress = false;
|
|
1906
|
+
return [];
|
|
1907
|
+
}
|
|
1908
|
+
const exchanges = this.observationBuffer.splice(0, this.observationBuffer.length);
|
|
1909
|
+
if (this.observationFlushTimer) {
|
|
1910
|
+
clearTimeout(this.observationFlushTimer);
|
|
1911
|
+
this.observationFlushTimer = null;
|
|
1912
|
+
}
|
|
1913
|
+
const OBSERVATION_EXTRACTION_PROMPT = `You are analyzing recent conversation exchanges between a user and an AI assistant.
|
|
1914
|
+
Extract any durable observations about the user that would be useful across future sessions.
|
|
1915
|
+
|
|
1916
|
+
Categories to look for:
|
|
1917
|
+
- Preferences (tools, languages, workflows, communication style)
|
|
1918
|
+
- Facts (role, location, projects they work on, tech stack)
|
|
1919
|
+
- Standing instructions (things they always/never want)
|
|
1920
|
+
- Patterns (recurring topics, how they like to work)
|
|
1921
|
+
|
|
1922
|
+
Return ONLY a JSON array of short observation strings (max 150 chars each).
|
|
1923
|
+
If nothing meaningful is found, return an empty array [].
|
|
1924
|
+
Do NOT include observations about the conversation itself, only about the user.
|
|
7
1925
|
|
|
8
|
-
|
|
9
|
-
|
|
1926
|
+
Recent exchanges:
|
|
1927
|
+
`;
|
|
1928
|
+
const exchangeText = exchanges.map((e, i) => `Exchange ${i + 1}:
|
|
1929
|
+
User: ${e.userPrompt.slice(0, 500)}
|
|
1930
|
+
Assistant: ${e.response.slice(0, 500)}`).join(`
|
|
1931
|
+
|
|
1932
|
+
`);
|
|
1933
|
+
const prompt = OBSERVATION_EXTRACTION_PROMPT + exchangeText;
|
|
1934
|
+
const runtimeAny = this.runtime;
|
|
1935
|
+
try {
|
|
1936
|
+
runtimeAny.__orchestratorTrajectoryCtx = {
|
|
1937
|
+
source: "orchestrator",
|
|
1938
|
+
decisionType: "observation-extraction"
|
|
1939
|
+
};
|
|
1940
|
+
const result = await this.runtime.useModel(ModelType.TEXT_SMALL, {
|
|
1941
|
+
prompt,
|
|
1942
|
+
maxTokens: 512,
|
|
1943
|
+
temperature: 0
|
|
1944
|
+
});
|
|
1945
|
+
const jsonMatch = result.match(/\[[\s\S]*\]/);
|
|
1946
|
+
if (!jsonMatch)
|
|
1947
|
+
return [];
|
|
1948
|
+
const parsed = JSON.parse(jsonMatch[0]);
|
|
1949
|
+
if (!Array.isArray(parsed))
|
|
1950
|
+
return [];
|
|
1951
|
+
const observations = parsed.filter((s) => typeof s === "string" && s.length > 0).map((s) => s.slice(0, 150));
|
|
1952
|
+
if (observations.length === 0)
|
|
1953
|
+
return [];
|
|
1954
|
+
const lastExchange = exchanges[exchanges.length - 1];
|
|
1955
|
+
await this.withTrajectoryWriteLock(lastExchange.trajectoryId, async () => {
|
|
1956
|
+
const trajectory = await this.getTrajectoryById(lastExchange.trajectoryId);
|
|
1957
|
+
if (trajectory) {
|
|
1958
|
+
const meta = trajectory.metadata ?? {};
|
|
1959
|
+
const existing = Array.isArray(meta.observations) ? meta.observations : [];
|
|
1960
|
+
meta.observations = [...existing, ...observations].slice(-30);
|
|
1961
|
+
trajectory.metadata = meta;
|
|
1962
|
+
await this.persistTrajectory(lastExchange.trajectoryId, trajectory, trajectory.metrics?.finalStatus || "completed");
|
|
1963
|
+
}
|
|
1964
|
+
});
|
|
1965
|
+
return observations;
|
|
1966
|
+
} catch {
|
|
1967
|
+
return [];
|
|
1968
|
+
} finally {
|
|
1969
|
+
delete runtimeAny.__orchestratorTrajectoryCtx;
|
|
1970
|
+
this.observationFlushInProgress = false;
|
|
1971
|
+
}
|
|
1972
|
+
}
|
|
10
1973
|
activeStepIds = new Map;
|
|
11
|
-
|
|
1974
|
+
stepToTrajectory = new Map;
|
|
1975
|
+
writeQueues = new Map;
|
|
1976
|
+
static async start(runtime) {
|
|
1977
|
+
const service = new this(runtime);
|
|
1978
|
+
await service.initialize();
|
|
1979
|
+
return service;
|
|
1980
|
+
}
|
|
1981
|
+
async stop() {
|
|
1982
|
+
this.enabled = false;
|
|
1983
|
+
}
|
|
1984
|
+
setEnabled(enabled) {
|
|
1985
|
+
this.enabled = enabled;
|
|
1986
|
+
}
|
|
1987
|
+
isEnabled() {
|
|
1988
|
+
return this.enabled;
|
|
1989
|
+
}
|
|
1990
|
+
async getSqlHelper() {
|
|
1991
|
+
const drizzle = await Promise.resolve().then(() => (init_drizzle_orm(), exports_drizzle_orm));
|
|
1992
|
+
return drizzle.sql;
|
|
1993
|
+
}
|
|
1994
|
+
async executeRawSql(sqlText) {
|
|
1995
|
+
const runtime = this.runtime;
|
|
1996
|
+
if (!runtime?.adapter) {
|
|
1997
|
+
throw new Error("Database adapter not available");
|
|
1998
|
+
}
|
|
1999
|
+
const sqlHelper = await this.getSqlHelper();
|
|
2000
|
+
const db = runtime.adapter.db;
|
|
2001
|
+
const query = sqlHelper.raw(sqlText);
|
|
2002
|
+
const result = await db.execute(query);
|
|
2003
|
+
const rows = Array.isArray(result.rows) ? result.rows : [];
|
|
2004
|
+
const columns = result.fields && Array.isArray(result.fields) ? result.fields.map((field) => field.name) : rows.length > 0 ? Object.keys(rows[0]) : [];
|
|
2005
|
+
return { rows, columns };
|
|
2006
|
+
}
|
|
2007
|
+
async initialize() {
|
|
2008
|
+
if (this.initialized)
|
|
2009
|
+
return;
|
|
2010
|
+
const runtime = this.runtime;
|
|
2011
|
+
if (!runtime?.adapter) {
|
|
2012
|
+
logger2.warn("[trajectory-logger] No runtime adapter available, skipping initialization");
|
|
2013
|
+
return;
|
|
2014
|
+
}
|
|
2015
|
+
await this.ensureTablesExist();
|
|
2016
|
+
await this.backfillTrajectoriesMissingLlmCalls();
|
|
2017
|
+
const originalUseModel = runtime.useModel;
|
|
2018
|
+
if (typeof originalUseModel === "function") {
|
|
2019
|
+
const patchedUseModel = async function(...args) {
|
|
2020
|
+
const context = getTrajectoryContext();
|
|
2021
|
+
if (context?.trajectoryStepId) {
|
|
2022
|
+
return originalUseModel.call(this, ...args);
|
|
2023
|
+
}
|
|
2024
|
+
const trajLogger = runtime.getService(TrajectoryLoggerService.serviceType);
|
|
2025
|
+
if (!trajLogger || !trajLogger.isEnabled()) {
|
|
2026
|
+
return originalUseModel.call(this, ...args);
|
|
2027
|
+
}
|
|
2028
|
+
const stepId = await trajLogger.startTrajectory(runtime.agentId, {
|
|
2029
|
+
source: "chat-orphan",
|
|
2030
|
+
metadata: { autoPatch: true }
|
|
2031
|
+
});
|
|
2032
|
+
try {
|
|
2033
|
+
return await runWithTrajectoryContext({ trajectoryStepId: stepId }, () => originalUseModel.call(this, ...args));
|
|
2034
|
+
} finally {
|
|
2035
|
+
await trajLogger.endTrajectory(stepId, "completed");
|
|
2036
|
+
}
|
|
2037
|
+
};
|
|
2038
|
+
runtime.useModel = patchedUseModel;
|
|
2039
|
+
}
|
|
2040
|
+
this.initialized = true;
|
|
2041
|
+
logger2.info("[trajectory-logger] Trajectory logger service initialized");
|
|
2042
|
+
}
|
|
2043
|
+
async getTableColumnNames(tableName) {
|
|
2044
|
+
const names = new Set;
|
|
2045
|
+
try {
|
|
2046
|
+
const result = await this.executeRawSql(`
|
|
2047
|
+
SELECT column_name
|
|
2048
|
+
FROM information_schema.columns
|
|
2049
|
+
WHERE table_name = ${sqlLiteral(tableName)}
|
|
2050
|
+
AND table_schema NOT IN ('pg_catalog', 'information_schema')
|
|
2051
|
+
`);
|
|
2052
|
+
for (const row of result.rows) {
|
|
2053
|
+
const name2 = asString(pickCell(row, "column_name"));
|
|
2054
|
+
if (name2)
|
|
2055
|
+
names.add(name2);
|
|
2056
|
+
}
|
|
2057
|
+
if (names.size > 0)
|
|
2058
|
+
return names;
|
|
2059
|
+
} catch {}
|
|
2060
|
+
const safeTableName = tableName.replace(/[^a-zA-Z0-9_]/g, "");
|
|
2061
|
+
if (!safeTableName)
|
|
2062
|
+
return names;
|
|
2063
|
+
try {
|
|
2064
|
+
const pragma = await this.executeRawSql(`PRAGMA table_info(${safeTableName})`);
|
|
2065
|
+
for (const row of pragma.rows) {
|
|
2066
|
+
const name2 = asString(pickCell(row, "name"));
|
|
2067
|
+
if (name2)
|
|
2068
|
+
names.add(name2);
|
|
2069
|
+
}
|
|
2070
|
+
} catch {}
|
|
2071
|
+
return names;
|
|
2072
|
+
}
|
|
2073
|
+
async ensureTrajectoryColumnsExist() {
|
|
2074
|
+
const columns = await this.getTableColumnNames("trajectories");
|
|
2075
|
+
const requiredColumns = [
|
|
2076
|
+
["scenario_id", "TEXT"],
|
|
2077
|
+
["episode_id", "TEXT"],
|
|
2078
|
+
["batch_id", "TEXT"],
|
|
2079
|
+
["group_index", "INTEGER"],
|
|
2080
|
+
["steps_json", "JSONB NOT NULL DEFAULT '[]'"],
|
|
2081
|
+
["reward_components_json", "JSONB NOT NULL DEFAULT '{}'"],
|
|
2082
|
+
["metrics_json", "JSONB NOT NULL DEFAULT '{}'"],
|
|
2083
|
+
["metadata_json", "JSONB NOT NULL DEFAULT '{}'"],
|
|
2084
|
+
["is_training_data", "BOOLEAN NOT NULL DEFAULT FALSE"],
|
|
2085
|
+
["is_evaluation", "BOOLEAN NOT NULL DEFAULT FALSE"],
|
|
2086
|
+
["used_in_training", "BOOLEAN NOT NULL DEFAULT FALSE"],
|
|
2087
|
+
["judged_at", "TIMESTAMPTZ"]
|
|
2088
|
+
];
|
|
2089
|
+
for (const [columnName, definition] of requiredColumns) {
|
|
2090
|
+
if (columns.has(columnName))
|
|
2091
|
+
continue;
|
|
2092
|
+
try {
|
|
2093
|
+
await this.executeRawSql(`
|
|
2094
|
+
ALTER TABLE trajectories
|
|
2095
|
+
ADD COLUMN IF NOT EXISTS ${columnName} ${definition}
|
|
2096
|
+
`);
|
|
2097
|
+
} catch (errWithIfExists) {
|
|
2098
|
+
try {
|
|
2099
|
+
await this.executeRawSql(`
|
|
2100
|
+
ALTER TABLE trajectories
|
|
2101
|
+
ADD COLUMN ${columnName} ${definition}
|
|
2102
|
+
`);
|
|
2103
|
+
} catch (errPlain) {
|
|
2104
|
+
const combinedMessage = `${errWithIfExists instanceof Error ? errWithIfExists.message : String(errWithIfExists)} | ${errPlain instanceof Error ? errPlain.message : String(errPlain)}`.toLowerCase();
|
|
2105
|
+
if (combinedMessage.includes("already exists") || combinedMessage.includes("duplicate column") || combinedMessage.includes("duplicate_column")) {
|
|
2106
|
+
continue;
|
|
2107
|
+
}
|
|
2108
|
+
logger2.warn(`[trajectory-logger] Failed to add trajectories.${columnName} (non-fatal): ${errPlain instanceof Error ? errPlain.message : String(errPlain)}`);
|
|
2109
|
+
}
|
|
2110
|
+
}
|
|
2111
|
+
}
|
|
2112
|
+
for (const statement of [
|
|
2113
|
+
`ALTER TABLE trajectories
|
|
2114
|
+
ALTER COLUMN start_time TYPE BIGINT USING start_time::BIGINT`,
|
|
2115
|
+
`ALTER TABLE trajectories
|
|
2116
|
+
ALTER COLUMN end_time TYPE BIGINT USING end_time::BIGINT`,
|
|
2117
|
+
`ALTER TABLE trajectories
|
|
2118
|
+
ALTER COLUMN duration_ms TYPE BIGINT USING duration_ms::BIGINT`
|
|
2119
|
+
]) {
|
|
2120
|
+
try {
|
|
2121
|
+
await this.executeRawSql(statement);
|
|
2122
|
+
} catch {}
|
|
2123
|
+
}
|
|
2124
|
+
}
|
|
2125
|
+
async ensureTablesExist() {
|
|
2126
|
+
await this.executeRawSql(`
|
|
2127
|
+
CREATE TABLE IF NOT EXISTS trajectories (
|
|
2128
|
+
id TEXT PRIMARY KEY,
|
|
2129
|
+
agent_id TEXT NOT NULL,
|
|
2130
|
+
source TEXT NOT NULL DEFAULT 'chat',
|
|
2131
|
+
status TEXT NOT NULL DEFAULT 'active',
|
|
2132
|
+
start_time BIGINT NOT NULL,
|
|
2133
|
+
end_time BIGINT,
|
|
2134
|
+
duration_ms BIGINT,
|
|
2135
|
+
step_count INTEGER NOT NULL DEFAULT 0,
|
|
2136
|
+
llm_call_count INTEGER NOT NULL DEFAULT 0,
|
|
2137
|
+
provider_access_count INTEGER NOT NULL DEFAULT 0,
|
|
2138
|
+
total_prompt_tokens INTEGER NOT NULL DEFAULT 0,
|
|
2139
|
+
total_completion_tokens INTEGER NOT NULL DEFAULT 0,
|
|
2140
|
+
total_reward REAL NOT NULL DEFAULT 0,
|
|
2141
|
+
scenario_id TEXT,
|
|
2142
|
+
episode_id TEXT,
|
|
2143
|
+
batch_id TEXT,
|
|
2144
|
+
group_index INTEGER,
|
|
2145
|
+
steps_json JSONB NOT NULL DEFAULT '[]',
|
|
2146
|
+
reward_components_json JSONB NOT NULL DEFAULT '{}',
|
|
2147
|
+
metrics_json JSONB NOT NULL DEFAULT '{}',
|
|
2148
|
+
metadata_json JSONB NOT NULL DEFAULT '{}',
|
|
2149
|
+
is_training_data BOOLEAN NOT NULL DEFAULT FALSE,
|
|
2150
|
+
is_evaluation BOOLEAN NOT NULL DEFAULT FALSE,
|
|
2151
|
+
used_in_training BOOLEAN NOT NULL DEFAULT FALSE,
|
|
2152
|
+
ai_judge_reward REAL,
|
|
2153
|
+
ai_judge_reasoning TEXT,
|
|
2154
|
+
judged_at TIMESTAMPTZ,
|
|
2155
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
2156
|
+
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
2157
|
+
)
|
|
2158
|
+
`);
|
|
2159
|
+
await this.ensureTrajectoryColumnsExist();
|
|
2160
|
+
try {
|
|
2161
|
+
await this.executeRawSql(`CREATE INDEX IF NOT EXISTS idx_trajectories_agent_id ON trajectories(agent_id)`);
|
|
2162
|
+
await this.executeRawSql(`CREATE INDEX IF NOT EXISTS idx_trajectories_source ON trajectories(source)`);
|
|
2163
|
+
await this.executeRawSql(`CREATE INDEX IF NOT EXISTS idx_trajectories_status ON trajectories(status)`);
|
|
2164
|
+
await this.executeRawSql(`CREATE INDEX IF NOT EXISTS idx_trajectories_created_at ON trajectories(created_at)`);
|
|
2165
|
+
await this.executeRawSql(`CREATE INDEX IF NOT EXISTS idx_trajectories_scenario_id ON trajectories(scenario_id)`);
|
|
2166
|
+
await this.executeRawSql(`CREATE INDEX IF NOT EXISTS idx_trajectories_batch_id ON trajectories(batch_id)`);
|
|
2167
|
+
await this.executeRawSql(`CREATE INDEX IF NOT EXISTS idx_trajectories_is_training ON trajectories(is_training_data)`);
|
|
2168
|
+
} catch (e) {
|
|
2169
|
+
logger2.warn(`[trajectory-logger] Failed to create indexes (non-fatal): ${e instanceof Error ? e.message : String(e)}`);
|
|
2170
|
+
}
|
|
2171
|
+
await this.executeRawSql(`
|
|
2172
|
+
CREATE TABLE IF NOT EXISTS trajectory_step_index (
|
|
2173
|
+
step_id TEXT PRIMARY KEY,
|
|
2174
|
+
trajectory_id TEXT NOT NULL REFERENCES trajectories(id) ON DELETE CASCADE,
|
|
2175
|
+
step_number INTEGER NOT NULL DEFAULT 0,
|
|
2176
|
+
is_active BOOLEAN NOT NULL DEFAULT FALSE,
|
|
2177
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
2178
|
+
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
2179
|
+
)
|
|
2180
|
+
`);
|
|
2181
|
+
await this.executeRawSql(`CREATE INDEX IF NOT EXISTS idx_trajectory_step_index_trajectory_id ON trajectory_step_index(trajectory_id)`);
|
|
2182
|
+
await this.executeRawSql(`CREATE INDEX IF NOT EXISTS idx_trajectory_step_index_is_active ON trajectory_step_index(is_active)`);
|
|
2183
|
+
}
|
|
2184
|
+
normalizeTrajectoryStatus(value) {
|
|
2185
|
+
switch (value) {
|
|
2186
|
+
case "active":
|
|
2187
|
+
case "completed":
|
|
2188
|
+
case "error":
|
|
2189
|
+
case "timeout":
|
|
2190
|
+
case "terminated":
|
|
2191
|
+
return value;
|
|
2192
|
+
default:
|
|
2193
|
+
return "completed";
|
|
2194
|
+
}
|
|
2195
|
+
}
|
|
2196
|
+
async backfillTrajectoriesMissingLlmCalls() {
|
|
2197
|
+
const maxRows = 2000;
|
|
2198
|
+
let fixed = 0;
|
|
2199
|
+
try {
|
|
2200
|
+
const rows = await this.executeRawSql(`
|
|
2201
|
+
SELECT id, status
|
|
2202
|
+
FROM trajectories
|
|
2203
|
+
WHERE COALESCE(llm_call_count, 0) = 0
|
|
2204
|
+
AND status <> 'active'
|
|
2205
|
+
ORDER BY created_at ASC
|
|
2206
|
+
LIMIT ${maxRows}
|
|
2207
|
+
`);
|
|
2208
|
+
for (const row of rows.rows) {
|
|
2209
|
+
const trajectoryId = asString(pickCell(row, "id"));
|
|
2210
|
+
if (!trajectoryId)
|
|
2211
|
+
continue;
|
|
2212
|
+
const status = this.normalizeTrajectoryStatus(asString(pickCell(row, "status")));
|
|
2213
|
+
await this.withTrajectoryWriteLock(trajectoryId, async () => {
|
|
2214
|
+
const trajectory = await this.getTrajectoryById(trajectoryId);
|
|
2215
|
+
if (!trajectory)
|
|
2216
|
+
return;
|
|
2217
|
+
const inserted = this.ensureAtLeastOneLlmCall(trajectory, "backfill");
|
|
2218
|
+
if (!inserted)
|
|
2219
|
+
return;
|
|
2220
|
+
await this.persistTrajectory(trajectoryId, trajectory, status);
|
|
2221
|
+
fixed += 1;
|
|
2222
|
+
});
|
|
2223
|
+
}
|
|
2224
|
+
if (fixed > 0) {
|
|
2225
|
+
logger2.info(`[trajectory-logger] Backfilled ${fixed} completed trajectories with synthetic LLM calls`);
|
|
2226
|
+
}
|
|
2227
|
+
if (rows.rows.length >= maxRows) {
|
|
2228
|
+
logger2.warn(`[trajectory-logger] Backfill hit safety cap (${maxRows}); remaining older trajectories will be fixed lazily when touched`);
|
|
2229
|
+
}
|
|
2230
|
+
} catch (err) {
|
|
2231
|
+
logger2.warn(`[trajectory-logger] Failed to backfill trajectories missing LLM calls (non-fatal): ${err instanceof Error ? err.message : String(err)}`);
|
|
2232
|
+
}
|
|
2233
|
+
}
|
|
2234
|
+
normalizePurpose(value) {
|
|
2235
|
+
switch (value) {
|
|
2236
|
+
case "action":
|
|
2237
|
+
case "reasoning":
|
|
2238
|
+
case "evaluation":
|
|
2239
|
+
case "response":
|
|
2240
|
+
case "other":
|
|
2241
|
+
return value;
|
|
2242
|
+
default:
|
|
2243
|
+
return "other";
|
|
2244
|
+
}
|
|
2245
|
+
}
|
|
2246
|
+
defaultEnvironmentState(timestamp = Date.now()) {
|
|
2247
|
+
return {
|
|
2248
|
+
timestamp,
|
|
2249
|
+
agentBalance: 0,
|
|
2250
|
+
agentPoints: 0,
|
|
2251
|
+
agentPnL: 0,
|
|
2252
|
+
openPositions: 0
|
|
2253
|
+
};
|
|
2254
|
+
}
|
|
2255
|
+
createPendingAction(stepTimestamp) {
|
|
2256
|
+
return {
|
|
2257
|
+
attemptId: "",
|
|
2258
|
+
timestamp: stepTimestamp,
|
|
2259
|
+
actionType: "pending",
|
|
2260
|
+
actionName: "pending",
|
|
2261
|
+
parameters: {},
|
|
2262
|
+
success: false
|
|
2263
|
+
};
|
|
2264
|
+
}
|
|
2265
|
+
createStep(stepId, stepNumber, envState) {
|
|
2266
|
+
const timestamp = envState.timestamp || Date.now();
|
|
2267
|
+
return {
|
|
2268
|
+
stepId,
|
|
2269
|
+
stepNumber,
|
|
2270
|
+
timestamp,
|
|
2271
|
+
environmentState: envState,
|
|
2272
|
+
observation: {},
|
|
2273
|
+
llmCalls: [],
|
|
2274
|
+
providerAccesses: [],
|
|
2275
|
+
action: this.createPendingAction(timestamp),
|
|
2276
|
+
reward: 0,
|
|
2277
|
+
done: false
|
|
2278
|
+
};
|
|
2279
|
+
}
|
|
2280
|
+
ensureAtLeastOneLlmCall(trajectory, source) {
|
|
2281
|
+
if (this.computeTotals(trajectory.steps).llmCallCount > 0) {
|
|
2282
|
+
return false;
|
|
2283
|
+
}
|
|
2284
|
+
const timestamp = Date.now();
|
|
2285
|
+
let step = trajectory.steps[trajectory.steps.length - 1];
|
|
2286
|
+
if (!step) {
|
|
2287
|
+
step = this.createStep(uuidv4(), 0, this.defaultEnvironmentState(timestamp));
|
|
2288
|
+
step.done = true;
|
|
2289
|
+
trajectory.steps.push(step);
|
|
2290
|
+
}
|
|
2291
|
+
if (!Array.isArray(step.llmCalls)) {
|
|
2292
|
+
step.llmCalls = [];
|
|
2293
|
+
}
|
|
2294
|
+
const syntheticCall = {
|
|
2295
|
+
callId: uuidv4(),
|
|
2296
|
+
timestamp,
|
|
2297
|
+
model: "milady/synthetic-trajectory-fallback",
|
|
2298
|
+
systemPrompt: "[synthetic] inserted by trajectory logger because no LLM calls were captured",
|
|
2299
|
+
userPrompt: "[synthetic] this trajectory completed without recorded model activity",
|
|
2300
|
+
response: "[synthetic] placeholder call inserted to enforce minimum llm_call_count=1",
|
|
2301
|
+
temperature: 0,
|
|
2302
|
+
maxTokens: 0,
|
|
2303
|
+
promptTokens: 0,
|
|
2304
|
+
completionTokens: 0,
|
|
2305
|
+
latencyMs: 0,
|
|
2306
|
+
purpose: "other",
|
|
2307
|
+
actionType: "TRAJECTORY_FALLBACK"
|
|
2308
|
+
};
|
|
2309
|
+
step.llmCalls.push(syntheticCall);
|
|
2310
|
+
if (!step.metadata)
|
|
2311
|
+
step.metadata = {};
|
|
2312
|
+
step.metadata.syntheticLlmCall = true;
|
|
2313
|
+
step.metadata.syntheticLlmCallSource = source;
|
|
2314
|
+
trajectory.metadata.syntheticLlmCall = true;
|
|
2315
|
+
trajectory.metadata.syntheticLlmCallSource = source;
|
|
2316
|
+
const existingFallbackCount = trajectory.metrics.syntheticLlmFallbackCount;
|
|
2317
|
+
trajectory.metrics.syntheticLlmFallbackCount = typeof existingFallbackCount === "number" && Number.isFinite(existingFallbackCount) ? existingFallbackCount + 1 : 1;
|
|
2318
|
+
return true;
|
|
2319
|
+
}
|
|
2320
|
+
computeTotals(steps) {
|
|
2321
|
+
let llmCallCount = 0;
|
|
2322
|
+
let providerAccessCount = 0;
|
|
2323
|
+
let totalPromptTokens = 0;
|
|
2324
|
+
let totalCompletionTokens = 0;
|
|
2325
|
+
for (const step of steps) {
|
|
2326
|
+
const llmCalls = Array.isArray(step.llmCalls) ? step.llmCalls : [];
|
|
2327
|
+
const providerAccesses = Array.isArray(step.providerAccesses) ? step.providerAccesses : [];
|
|
2328
|
+
llmCallCount += llmCalls.length;
|
|
2329
|
+
providerAccessCount += providerAccesses.length;
|
|
2330
|
+
for (const call of llmCalls) {
|
|
2331
|
+
totalPromptTokens += call.promptTokens ?? 0;
|
|
2332
|
+
totalCompletionTokens += call.completionTokens ?? 0;
|
|
2333
|
+
}
|
|
2334
|
+
}
|
|
2335
|
+
return {
|
|
2336
|
+
stepCount: steps.length,
|
|
2337
|
+
llmCallCount,
|
|
2338
|
+
providerAccessCount,
|
|
2339
|
+
totalPromptTokens,
|
|
2340
|
+
totalCompletionTokens
|
|
2341
|
+
};
|
|
2342
|
+
}
|
|
2343
|
+
async withTrajectoryWriteLock(trajectoryId, task) {
|
|
2344
|
+
const previous = this.writeQueues.get(trajectoryId) ?? Promise.resolve();
|
|
2345
|
+
const next = previous.catch(() => {}).then(task);
|
|
2346
|
+
this.writeQueues.set(trajectoryId, next);
|
|
2347
|
+
try {
|
|
2348
|
+
await next;
|
|
2349
|
+
} finally {
|
|
2350
|
+
if (this.writeQueues.get(trajectoryId) === next) {
|
|
2351
|
+
this.writeQueues.delete(trajectoryId);
|
|
2352
|
+
}
|
|
2353
|
+
}
|
|
2354
|
+
}
|
|
2355
|
+
async getTrajectoryById(trajectoryId) {
|
|
2356
|
+
const result = await this.executeRawSql(`SELECT * FROM trajectories WHERE id = ${sqlLiteral(trajectoryId)} LIMIT 1`);
|
|
2357
|
+
if (result.rows.length === 0)
|
|
2358
|
+
return null;
|
|
2359
|
+
return this.rowToTrajectory(result.rows[0]);
|
|
2360
|
+
}
|
|
2361
|
+
async getStepIndex(stepId) {
|
|
2362
|
+
const result = await this.executeRawSql(`SELECT trajectory_id, step_number, is_active FROM trajectory_step_index WHERE step_id = ${sqlLiteral(stepId)} LIMIT 1`);
|
|
2363
|
+
const row = result.rows[0];
|
|
2364
|
+
if (!row)
|
|
2365
|
+
return null;
|
|
2366
|
+
const trajectoryId = asString(pickCell(row, "trajectory_id"));
|
|
2367
|
+
if (!trajectoryId)
|
|
2368
|
+
return null;
|
|
2369
|
+
const stepNumber = asNumber(pickCell(row, "step_number")) ?? 0;
|
|
2370
|
+
const isActiveText = asString(pickCell(row, "is_active"));
|
|
2371
|
+
const isActive = isActiveText === "true" || isActiveText === "t" || pickCell(row, "is_active") === true;
|
|
2372
|
+
return { trajectoryId, stepNumber, isActive };
|
|
2373
|
+
}
|
|
2374
|
+
async setStepIndex(stepId, trajectoryId, stepNumber, isActive) {
|
|
2375
|
+
await this.executeRawSql(`
|
|
2376
|
+
INSERT INTO trajectory_step_index (
|
|
2377
|
+
step_id, trajectory_id, step_number, is_active, updated_at
|
|
2378
|
+
) VALUES (
|
|
2379
|
+
${sqlLiteral(stepId)},
|
|
2380
|
+
${sqlLiteral(trajectoryId)},
|
|
2381
|
+
${stepNumber},
|
|
2382
|
+
${isActive ? "TRUE" : "FALSE"},
|
|
2383
|
+
CURRENT_TIMESTAMP
|
|
2384
|
+
)
|
|
2385
|
+
ON CONFLICT (step_id) DO UPDATE SET
|
|
2386
|
+
trajectory_id = EXCLUDED.trajectory_id,
|
|
2387
|
+
step_number = EXCLUDED.step_number,
|
|
2388
|
+
is_active = EXCLUDED.is_active,
|
|
2389
|
+
updated_at = CURRENT_TIMESTAMP
|
|
2390
|
+
`);
|
|
2391
|
+
}
|
|
2392
|
+
async markAllStepsInactive(trajectoryId) {
|
|
2393
|
+
await this.executeRawSql(`
|
|
2394
|
+
UPDATE trajectory_step_index
|
|
2395
|
+
SET is_active = FALSE, updated_at = CURRENT_TIMESTAMP
|
|
2396
|
+
WHERE trajectory_id = ${sqlLiteral(trajectoryId)}
|
|
2397
|
+
`);
|
|
2398
|
+
}
|
|
2399
|
+
async resolveTrajectoryId(stepIdOrTrajectoryId) {
|
|
2400
|
+
const cached = this.stepToTrajectory.get(stepIdOrTrajectoryId);
|
|
2401
|
+
if (cached)
|
|
2402
|
+
return cached;
|
|
2403
|
+
const byStep = await this.getStepIndex(stepIdOrTrajectoryId);
|
|
2404
|
+
if (byStep?.trajectoryId) {
|
|
2405
|
+
this.stepToTrajectory.set(stepIdOrTrajectoryId, byStep.trajectoryId);
|
|
2406
|
+
return byStep.trajectoryId;
|
|
2407
|
+
}
|
|
2408
|
+
const byId = await this.executeRawSql(`SELECT id FROM trajectories WHERE id = ${sqlLiteral(stepIdOrTrajectoryId)} LIMIT 1`);
|
|
2409
|
+
const row = byId.rows[0];
|
|
2410
|
+
const id = row ? asString(pickCell(row, "id")) : null;
|
|
2411
|
+
return id;
|
|
2412
|
+
}
|
|
2413
|
+
async getCurrentStepIdFromDb(trajectoryId) {
|
|
2414
|
+
const result = await this.executeRawSql(`
|
|
2415
|
+
SELECT step_id
|
|
2416
|
+
FROM trajectory_step_index
|
|
2417
|
+
WHERE trajectory_id = ${sqlLiteral(trajectoryId)} AND is_active = TRUE
|
|
2418
|
+
ORDER BY step_number DESC, updated_at DESC
|
|
2419
|
+
LIMIT 1
|
|
2420
|
+
`);
|
|
2421
|
+
const row = result.rows[0];
|
|
2422
|
+
return row ? asString(pickCell(row, "step_id")) : null;
|
|
2423
|
+
}
|
|
2424
|
+
async persistTrajectory(trajectoryId, trajectory, status = "active") {
|
|
2425
|
+
if (status !== "active") {
|
|
2426
|
+
this.ensureAtLeastOneLlmCall(trajectory, "finalize");
|
|
2427
|
+
}
|
|
2428
|
+
const totals = this.computeTotals(trajectory.steps);
|
|
2429
|
+
const isFinalStatus = status !== "active";
|
|
2430
|
+
const persistedEndTime = isFinalStatus ? trajectory.endTime : null;
|
|
2431
|
+
const persistedDuration = isFinalStatus ? trajectory.durationMs : null;
|
|
2432
|
+
const updatedAtIso = new Date().toISOString();
|
|
2433
|
+
try {
|
|
2434
|
+
await this.executeRawSql(`
|
|
2435
|
+
UPDATE trajectories SET
|
|
2436
|
+
status = ${sqlLiteral(status)},
|
|
2437
|
+
end_time = ${sqlLiteral(persistedEndTime)},
|
|
2438
|
+
duration_ms = ${sqlLiteral(persistedDuration)},
|
|
2439
|
+
step_count = ${totals.stepCount},
|
|
2440
|
+
llm_call_count = ${totals.llmCallCount},
|
|
2441
|
+
provider_access_count = ${totals.providerAccessCount},
|
|
2442
|
+
total_prompt_tokens = ${totals.totalPromptTokens},
|
|
2443
|
+
total_completion_tokens = ${totals.totalCompletionTokens},
|
|
2444
|
+
total_reward = ${trajectory.totalReward},
|
|
2445
|
+
steps_json = ${sqlLiteral(trajectory.steps)},
|
|
2446
|
+
reward_components_json = ${sqlLiteral(trajectory.rewardComponents)},
|
|
2447
|
+
metrics_json = ${sqlLiteral(trajectory.metrics)},
|
|
2448
|
+
metadata_json = ${sqlLiteral(trajectory.metadata)},
|
|
2449
|
+
updated_at = ${sqlLiteral(updatedAtIso)}
|
|
2450
|
+
WHERE id = ${sqlLiteral(trajectoryId)}
|
|
2451
|
+
`);
|
|
2452
|
+
} catch (modernErr) {
|
|
2453
|
+
await this.executeRawSql(`
|
|
2454
|
+
UPDATE trajectories SET
|
|
2455
|
+
status = ${sqlLiteral(status)},
|
|
2456
|
+
end_time = ${sqlLiteral(persistedEndTime)},
|
|
2457
|
+
duration_ms = ${sqlLiteral(persistedDuration)},
|
|
2458
|
+
step_count = ${totals.stepCount},
|
|
2459
|
+
llm_call_count = ${totals.llmCallCount},
|
|
2460
|
+
provider_access_count = ${totals.providerAccessCount},
|
|
2461
|
+
total_prompt_tokens = ${totals.totalPromptTokens},
|
|
2462
|
+
total_completion_tokens = ${totals.totalCompletionTokens},
|
|
2463
|
+
total_reward = ${trajectory.totalReward},
|
|
2464
|
+
steps_json = ${sqlLiteral(trajectory.steps)},
|
|
2465
|
+
metadata = ${sqlLiteral(trajectory.metadata)},
|
|
2466
|
+
updated_at = ${sqlLiteral(updatedAtIso)}
|
|
2467
|
+
WHERE id = ${sqlLiteral(trajectoryId)}
|
|
2468
|
+
`).catch((legacyErr) => {
|
|
2469
|
+
logger2.warn({ err: legacyErr, trajectoryId }, `[trajectory-logger] Failed to persist trajectory update after compatibility fallback: ${modernErr instanceof Error ? modernErr.message : String(modernErr)}`);
|
|
2470
|
+
throw legacyErr;
|
|
2471
|
+
});
|
|
2472
|
+
}
|
|
2473
|
+
}
|
|
2474
|
+
async ensureStepExists(trajectory, stepId) {
|
|
2475
|
+
let step = trajectory.steps.find((entry) => entry.stepId === stepId);
|
|
2476
|
+
if (step) {
|
|
2477
|
+
if (!Array.isArray(step.llmCalls))
|
|
2478
|
+
step.llmCalls = [];
|
|
2479
|
+
if (!Array.isArray(step.providerAccesses))
|
|
2480
|
+
step.providerAccesses = [];
|
|
2481
|
+
return step;
|
|
2482
|
+
}
|
|
2483
|
+
const index = await this.getStepIndex(stepId);
|
|
2484
|
+
const stepNumber = index?.stepNumber ?? trajectory.steps.length;
|
|
2485
|
+
step = this.createStep(stepId, stepNumber, this.defaultEnvironmentState());
|
|
2486
|
+
trajectory.steps.push(step);
|
|
2487
|
+
trajectory.steps.sort((a, b) => a.stepNumber - b.stepNumber);
|
|
2488
|
+
return step;
|
|
2489
|
+
}
|
|
2490
|
+
logLlmCall(params) {
|
|
2491
|
+
if (!this.enabled)
|
|
2492
|
+
return;
|
|
2493
|
+
if (shouldSuppressNoInputEmbeddingCall(params))
|
|
2494
|
+
return;
|
|
2495
|
+
const orchestratorCtx = readOrchestratorTrajectoryContext(this.runtime);
|
|
2496
|
+
(async () => {
|
|
2497
|
+
const trajectoryId = await this.resolveTrajectoryId(params.stepId);
|
|
2498
|
+
if (!trajectoryId) {
|
|
2499
|
+
logger2.debug({ stepId: params.stepId }, "[trajectory-logger] No trajectory mapping for LLM call");
|
|
2500
|
+
return;
|
|
2501
|
+
}
|
|
2502
|
+
await this.withTrajectoryWriteLock(trajectoryId, async () => {
|
|
2503
|
+
const trajectory = await this.getTrajectoryById(trajectoryId);
|
|
2504
|
+
if (!trajectory)
|
|
2505
|
+
return;
|
|
2506
|
+
if (orchestratorCtx) {
|
|
2507
|
+
trajectory.source = "orchestrator";
|
|
2508
|
+
if (!trajectory.metadata)
|
|
2509
|
+
trajectory.metadata = {};
|
|
2510
|
+
trajectory.metadata.orchestrator = { ...orchestratorCtx };
|
|
2511
|
+
}
|
|
2512
|
+
const fullResponse = String(params.response || "");
|
|
2513
|
+
const purposeText = orchestratorCtx?.decisionType ?? String(params.purpose || "action");
|
|
2514
|
+
const insights = extractInsightsFromResponse(fullResponse, purposeText);
|
|
2515
|
+
if (insights.length > 0) {
|
|
2516
|
+
if (!trajectory.metadata)
|
|
2517
|
+
trajectory.metadata = {};
|
|
2518
|
+
const existing = Array.isArray(trajectory.metadata.insights) ? trajectory.metadata.insights : [];
|
|
2519
|
+
trajectory.metadata.insights = [...existing, ...insights].slice(-20);
|
|
2520
|
+
}
|
|
2521
|
+
const step = await this.ensureStepExists(trajectory, params.stepId);
|
|
2522
|
+
const llmCall = {
|
|
2523
|
+
callId: uuidv4(),
|
|
2524
|
+
timestamp: Date.now(),
|
|
2525
|
+
model: params.model,
|
|
2526
|
+
modelVersion: params.modelVersion,
|
|
2527
|
+
systemPrompt: params.systemPrompt,
|
|
2528
|
+
userPrompt: params.userPrompt,
|
|
2529
|
+
response: params.response,
|
|
2530
|
+
reasoning: params.reasoning,
|
|
2531
|
+
temperature: params.temperature,
|
|
2532
|
+
maxTokens: params.maxTokens,
|
|
2533
|
+
purpose: this.normalizePurpose(purposeText),
|
|
2534
|
+
actionType: orchestratorCtx ? "orchestrator.useModel" : params.actionType || "runtime.useModel",
|
|
2535
|
+
promptTokens: params.promptTokens,
|
|
2536
|
+
completionTokens: params.completionTokens,
|
|
2537
|
+
latencyMs: params.latencyMs
|
|
2538
|
+
};
|
|
2539
|
+
step.llmCalls.push(llmCall);
|
|
2540
|
+
trajectory.startTime = Math.min(trajectory.startTime, llmCall.timestamp);
|
|
2541
|
+
trajectory.endTime = Math.max(trajectory.endTime ?? llmCall.timestamp, llmCall.timestamp);
|
|
2542
|
+
await this.persistTrajectory(trajectoryId, trajectory, "active");
|
|
2543
|
+
if (!orchestratorCtx && trajectory.source === "chat" && shouldRunObservationExtraction(this.runtime)) {
|
|
2544
|
+
this.pushChatExchange({
|
|
2545
|
+
userPrompt: String(params.userPrompt ?? ""),
|
|
2546
|
+
response: fullResponse,
|
|
2547
|
+
trajectoryId,
|
|
2548
|
+
timestamp: llmCall.timestamp
|
|
2549
|
+
});
|
|
2550
|
+
}
|
|
2551
|
+
});
|
|
2552
|
+
})().catch((err) => {
|
|
2553
|
+
logger2.warn({ err, stepId: params.stepId }, "[trajectory-logger] Failed to persist LLM call");
|
|
2554
|
+
});
|
|
2555
|
+
}
|
|
2556
|
+
logLLMCall(stepId, details) {
|
|
2557
|
+
this.logLlmCall({
|
|
2558
|
+
stepId,
|
|
2559
|
+
model: details.model,
|
|
2560
|
+
modelVersion: details.modelVersion,
|
|
2561
|
+
systemPrompt: details.systemPrompt,
|
|
2562
|
+
userPrompt: details.userPrompt,
|
|
2563
|
+
response: details.response,
|
|
2564
|
+
reasoning: details.reasoning,
|
|
2565
|
+
temperature: details.temperature,
|
|
2566
|
+
maxTokens: details.maxTokens,
|
|
2567
|
+
purpose: details.purpose,
|
|
2568
|
+
actionType: details.actionType ?? "",
|
|
2569
|
+
latencyMs: details.latencyMs ?? 0,
|
|
2570
|
+
promptTokens: details.promptTokens,
|
|
2571
|
+
completionTokens: details.completionTokens
|
|
2572
|
+
});
|
|
2573
|
+
}
|
|
2574
|
+
logProviderAccess(arg1, arg2) {
|
|
2575
|
+
if (!this.enabled)
|
|
2576
|
+
return;
|
|
2577
|
+
const params = typeof arg1 === "string" ? {
|
|
2578
|
+
stepId: arg1,
|
|
2579
|
+
providerName: arg2?.providerName ?? "unknown",
|
|
2580
|
+
data: arg2?.data ?? {},
|
|
2581
|
+
purpose: arg2?.purpose ?? "other",
|
|
2582
|
+
query: arg2?.query
|
|
2583
|
+
} : arg1;
|
|
2584
|
+
(async () => {
|
|
2585
|
+
const trajectoryId = await this.resolveTrajectoryId(params.stepId);
|
|
2586
|
+
if (!trajectoryId) {
|
|
2587
|
+
logger2.debug({ stepId: params.stepId }, "[trajectory-logger] No trajectory mapping for provider access");
|
|
2588
|
+
return;
|
|
2589
|
+
}
|
|
2590
|
+
await this.withTrajectoryWriteLock(trajectoryId, async () => {
|
|
2591
|
+
const trajectory = await this.getTrajectoryById(trajectoryId);
|
|
2592
|
+
if (!trajectory)
|
|
2593
|
+
return;
|
|
2594
|
+
const step = await this.ensureStepExists(trajectory, params.stepId);
|
|
2595
|
+
const access = {
|
|
2596
|
+
providerId: uuidv4(),
|
|
2597
|
+
providerName: params.providerName,
|
|
2598
|
+
timestamp: Date.now(),
|
|
2599
|
+
data: params.data,
|
|
2600
|
+
query: params.query,
|
|
2601
|
+
purpose: params.purpose
|
|
2602
|
+
};
|
|
2603
|
+
step.providerAccesses.push(access);
|
|
2604
|
+
await this.persistTrajectory(trajectoryId, trajectory, "active");
|
|
2605
|
+
});
|
|
2606
|
+
})().catch((err) => {
|
|
2607
|
+
logger2.warn({ err, stepId: params.stepId }, "[trajectory-logger] Failed to persist provider access");
|
|
2608
|
+
});
|
|
2609
|
+
}
|
|
2610
|
+
logProviderAccessByTrajectoryId(trajectoryId, access) {
|
|
2611
|
+
const stepId = this.getCurrentStepId(trajectoryId);
|
|
2612
|
+
if (!stepId) {
|
|
2613
|
+
logger2.debug({ trajectoryId }, "[trajectory-logger] No active step for provider access by trajectory");
|
|
2614
|
+
return;
|
|
2615
|
+
}
|
|
2616
|
+
this.logProviderAccess(stepId, access);
|
|
2617
|
+
}
|
|
2618
|
+
async startTrajectory(stepIdOrAgentId, options = {}) {
|
|
2619
|
+
if (!this.enabled)
|
|
2620
|
+
return uuidv4();
|
|
2621
|
+
const legacyStepId = typeof options.agentId === "string" && options.agentId.length > 0 ? stepIdOrAgentId : null;
|
|
2622
|
+
const agentId = (typeof options.agentId === "string" && options.agentId.length > 0 ? options.agentId : stepIdOrAgentId) ?? stepIdOrAgentId;
|
|
12
2623
|
const trajectoryId = uuidv4();
|
|
13
2624
|
const now = Date.now();
|
|
2625
|
+
const timestampIso = new Date(now).toISOString();
|
|
2626
|
+
const metadata = {
|
|
2627
|
+
...options.metadata ?? {}
|
|
2628
|
+
};
|
|
2629
|
+
if (options.roomId)
|
|
2630
|
+
metadata.roomId = options.roomId;
|
|
2631
|
+
if (options.entityId)
|
|
2632
|
+
metadata.entityId = options.entityId;
|
|
14
2633
|
const trajectory = {
|
|
15
|
-
trajectoryId
|
|
16
|
-
agentId
|
|
2634
|
+
trajectoryId,
|
|
2635
|
+
agentId,
|
|
17
2636
|
startTime: now,
|
|
18
2637
|
endTime: now,
|
|
19
2638
|
durationMs: 0,
|
|
20
|
-
episodeId: options.episodeId,
|
|
21
2639
|
scenarioId: options.scenarioId,
|
|
2640
|
+
episodeId: options.episodeId,
|
|
22
2641
|
batchId: options.batchId,
|
|
23
2642
|
groupIndex: options.groupIndex,
|
|
24
2643
|
steps: [],
|
|
25
2644
|
totalReward: 0,
|
|
26
|
-
rewardComponents: {
|
|
27
|
-
environmentReward: 0
|
|
28
|
-
},
|
|
2645
|
+
rewardComponents: { environmentReward: 0 },
|
|
29
2646
|
metrics: {
|
|
30
2647
|
episodeLength: 0,
|
|
31
2648
|
finalStatus: "completed"
|
|
32
2649
|
},
|
|
33
|
-
metadata:
|
|
2650
|
+
metadata: {
|
|
2651
|
+
source: options.source ?? "chat",
|
|
2652
|
+
...metadata
|
|
2653
|
+
}
|
|
34
2654
|
};
|
|
35
|
-
|
|
2655
|
+
let persistedStart = false;
|
|
2656
|
+
try {
|
|
2657
|
+
await this.executeRawSql(`
|
|
2658
|
+
INSERT INTO trajectories (
|
|
2659
|
+
id, agent_id, source, status, start_time, scenario_id, episode_id,
|
|
2660
|
+
batch_id, group_index, metadata_json, steps_json, reward_components_json, metrics_json,
|
|
2661
|
+
created_at, updated_at
|
|
2662
|
+
) VALUES (
|
|
2663
|
+
${sqlLiteral(trajectoryId)},
|
|
2664
|
+
${sqlLiteral(agentId)},
|
|
2665
|
+
${sqlLiteral(options.source ?? "chat")},
|
|
2666
|
+
'active',
|
|
2667
|
+
${now},
|
|
2668
|
+
${sqlLiteral(options.scenarioId ?? null)},
|
|
2669
|
+
${sqlLiteral(options.episodeId ?? null)},
|
|
2670
|
+
${sqlLiteral(options.batchId ?? null)},
|
|
2671
|
+
${options.groupIndex ?? "NULL"},
|
|
2672
|
+
${sqlLiteral(trajectory.metadata)},
|
|
2673
|
+
${sqlLiteral([])},
|
|
2674
|
+
${sqlLiteral(trajectory.rewardComponents)},
|
|
2675
|
+
${sqlLiteral(trajectory.metrics)},
|
|
2676
|
+
${sqlLiteral(timestampIso)},
|
|
2677
|
+
${sqlLiteral(timestampIso)}
|
|
2678
|
+
)
|
|
2679
|
+
`);
|
|
2680
|
+
persistedStart = true;
|
|
2681
|
+
} catch (err) {
|
|
2682
|
+
try {
|
|
2683
|
+
await this.executeRawSql(`
|
|
2684
|
+
INSERT INTO trajectories (
|
|
2685
|
+
id, agent_id, source, status, start_time, steps_json, metadata, created_at, updated_at
|
|
2686
|
+
) VALUES (
|
|
2687
|
+
${sqlLiteral(trajectoryId)},
|
|
2688
|
+
${sqlLiteral(agentId)},
|
|
2689
|
+
${sqlLiteral(options.source ?? "chat")},
|
|
2690
|
+
'active',
|
|
2691
|
+
${now},
|
|
2692
|
+
${sqlLiteral([])},
|
|
2693
|
+
${sqlLiteral(trajectory.metadata)},
|
|
2694
|
+
${sqlLiteral(timestampIso)},
|
|
2695
|
+
${sqlLiteral(timestampIso)}
|
|
2696
|
+
)
|
|
2697
|
+
`);
|
|
2698
|
+
persistedStart = true;
|
|
2699
|
+
} catch (legacyErr) {
|
|
2700
|
+
logger2.warn({ err: legacyErr, trajectoryId }, "[trajectory-logger] Failed to persist trajectory start");
|
|
2701
|
+
}
|
|
2702
|
+
}
|
|
2703
|
+
if (persistedStart && legacyStepId) {
|
|
2704
|
+
this.stepToTrajectory.set(legacyStepId, trajectoryId);
|
|
2705
|
+
try {
|
|
2706
|
+
await this.setStepIndex(legacyStepId, trajectoryId, -1, false);
|
|
2707
|
+
} catch (indexErr) {
|
|
2708
|
+
logger2.warn({ err: indexErr, trajectoryId, stepId: legacyStepId }, "[trajectory-logger] Failed to persist step index for trajectory start");
|
|
2709
|
+
}
|
|
2710
|
+
}
|
|
36
2711
|
return trajectoryId;
|
|
37
2712
|
}
|
|
38
2713
|
startStep(trajectoryId, envState) {
|
|
2714
|
+
if (!this.enabled)
|
|
2715
|
+
return uuidv4();
|
|
39
2716
|
const stepId = uuidv4();
|
|
40
|
-
const trajectory = this.activeTrajectories.get(trajectoryId);
|
|
41
|
-
if (!trajectory) {
|
|
42
|
-
throw new Error(`Trajectory ${trajectoryId} not found`);
|
|
43
|
-
}
|
|
44
|
-
const step = {
|
|
45
|
-
stepId: asUUID(stepId),
|
|
46
|
-
stepNumber: trajectory.steps.length,
|
|
47
|
-
timestamp: envState.timestamp || Date.now(),
|
|
48
|
-
environmentState: envState,
|
|
49
|
-
observation: {},
|
|
50
|
-
llmCalls: [],
|
|
51
|
-
providerAccesses: [],
|
|
52
|
-
action: {
|
|
53
|
-
attemptId: "",
|
|
54
|
-
timestamp: 0,
|
|
55
|
-
actionType: "pending",
|
|
56
|
-
actionName: "pending",
|
|
57
|
-
parameters: {},
|
|
58
|
-
success: false
|
|
59
|
-
},
|
|
60
|
-
reward: 0,
|
|
61
|
-
done: false
|
|
62
|
-
};
|
|
63
|
-
trajectory.steps.push(step);
|
|
64
2717
|
this.activeStepIds.set(trajectoryId, stepId);
|
|
2718
|
+
this.stepToTrajectory.set(stepId, trajectoryId);
|
|
2719
|
+
this.withTrajectoryWriteLock(trajectoryId, async () => {
|
|
2720
|
+
const trajectory = await this.getTrajectoryById(trajectoryId);
|
|
2721
|
+
if (!trajectory) {
|
|
2722
|
+
logger2.warn({ trajectoryId }, "[trajectory-logger] Trajectory not found for startStep");
|
|
2723
|
+
return;
|
|
2724
|
+
}
|
|
2725
|
+
const step = this.createStep(stepId, trajectory.steps.length, envState);
|
|
2726
|
+
trajectory.steps.push(step);
|
|
2727
|
+
await this.markAllStepsInactive(trajectoryId);
|
|
2728
|
+
await this.setStepIndex(stepId, trajectoryId, step.stepNumber, true);
|
|
2729
|
+
await this.persistTrajectory(trajectoryId, trajectory, "active");
|
|
2730
|
+
}).catch((err) => {
|
|
2731
|
+
logger2.warn({ err, trajectoryId, stepId }, "[trajectory-logger] Failed to persist startStep");
|
|
2732
|
+
});
|
|
65
2733
|
return stepId;
|
|
66
2734
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
if (!trajectory) {
|
|
70
|
-
logger.warn({ stepId }, "Trajectory not found for LLM call");
|
|
2735
|
+
completeStep(trajectoryId, actionOrStepId, actionOrReward, maybeReward) {
|
|
2736
|
+
if (!this.enabled)
|
|
71
2737
|
return;
|
|
72
|
-
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
2738
|
+
const explicitStepId = typeof actionOrStepId === "string" ? actionOrStepId : null;
|
|
2739
|
+
const action = typeof actionOrStepId === "string" ? actionOrReward : actionOrStepId;
|
|
2740
|
+
const rewardInfo = typeof actionOrStepId === "string" ? maybeReward : actionOrReward;
|
|
2741
|
+
if (!action)
|
|
76
2742
|
return;
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
2743
|
+
this.withTrajectoryWriteLock(trajectoryId, async () => {
|
|
2744
|
+
const trajectory = await this.getTrajectoryById(trajectoryId);
|
|
2745
|
+
if (!trajectory)
|
|
2746
|
+
return;
|
|
2747
|
+
const stepId = explicitStepId ?? this.activeStepIds.get(trajectoryId) ?? await this.getCurrentStepIdFromDb(trajectoryId);
|
|
2748
|
+
if (!stepId)
|
|
2749
|
+
return;
|
|
2750
|
+
const step = await this.ensureStepExists(trajectory, stepId);
|
|
2751
|
+
step.action = {
|
|
2752
|
+
attemptId: uuidv4(),
|
|
2753
|
+
timestamp: Date.now(),
|
|
2754
|
+
...action
|
|
2755
|
+
};
|
|
2756
|
+
step.done = true;
|
|
2757
|
+
if (rewardInfo?.reward !== undefined) {
|
|
2758
|
+
step.reward = rewardInfo.reward;
|
|
2759
|
+
trajectory.totalReward += rewardInfo.reward;
|
|
2760
|
+
}
|
|
2761
|
+
if (rewardInfo?.components) {
|
|
2762
|
+
trajectory.rewardComponents = {
|
|
2763
|
+
...trajectory.rewardComponents,
|
|
2764
|
+
...rewardInfo.components
|
|
2765
|
+
};
|
|
2766
|
+
}
|
|
2767
|
+
await this.setStepIndex(stepId, trajectoryId, step.stepNumber, false);
|
|
2768
|
+
this.activeStepIds.delete(trajectoryId);
|
|
2769
|
+
await this.persistTrajectory(trajectoryId, trajectory, "active");
|
|
2770
|
+
}).catch((err) => {
|
|
2771
|
+
logger2.warn({ err, trajectoryId }, "[trajectory-logger] Failed to complete step");
|
|
2772
|
+
});
|
|
84
2773
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
if (!trajectory) {
|
|
88
|
-
logger.warn({ stepId }, "Trajectory not found for provider access");
|
|
2774
|
+
async endTrajectory(stepIdOrTrajectoryId, status = "completed", finalMetrics) {
|
|
2775
|
+
if (!this.enabled)
|
|
89
2776
|
return;
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
logger.warn({ stepId }, "Step not found for provider access");
|
|
2777
|
+
const trajectoryId = await this.resolveTrajectoryId(stepIdOrTrajectoryId);
|
|
2778
|
+
if (!trajectoryId) {
|
|
2779
|
+
logger2.debug({ stepIdOrTrajectoryId }, "[trajectory-logger] No trajectory to end");
|
|
94
2780
|
return;
|
|
95
2781
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
2782
|
+
await this.withTrajectoryWriteLock(trajectoryId, async () => {
|
|
2783
|
+
const trajectory = await this.getTrajectoryById(trajectoryId);
|
|
2784
|
+
if (!trajectory) {
|
|
2785
|
+
logger2.debug({ trajectoryId }, "[trajectory-logger] Trajectory not found while ending");
|
|
2786
|
+
return;
|
|
2787
|
+
}
|
|
2788
|
+
const now = Date.now();
|
|
2789
|
+
trajectory.endTime = now;
|
|
2790
|
+
trajectory.durationMs = now - trajectory.startTime;
|
|
2791
|
+
trajectory.metrics.finalStatus = status;
|
|
2792
|
+
trajectory.metrics.episodeLength = trajectory.steps.length;
|
|
2793
|
+
if (finalMetrics) {
|
|
2794
|
+
trajectory.metrics = {
|
|
2795
|
+
...trajectory.metrics,
|
|
2796
|
+
...finalMetrics
|
|
2797
|
+
};
|
|
2798
|
+
}
|
|
2799
|
+
await this.markAllStepsInactive(trajectoryId);
|
|
2800
|
+
this.activeStepIds.delete(trajectoryId);
|
|
2801
|
+
await this.persistTrajectory(trajectoryId, trajectory, status);
|
|
2802
|
+
});
|
|
2803
|
+
for (const [stepId, mappedTrajectoryId] of this.stepToTrajectory.entries()) {
|
|
2804
|
+
if (mappedTrajectoryId === trajectoryId) {
|
|
2805
|
+
this.stepToTrajectory.delete(stepId);
|
|
2806
|
+
}
|
|
108
2807
|
}
|
|
109
|
-
this.logLLMCall(stepId, llmCall);
|
|
110
2808
|
}
|
|
111
|
-
|
|
112
|
-
const
|
|
113
|
-
if (!
|
|
114
|
-
|
|
115
|
-
return;
|
|
2809
|
+
async listTrajectories(options = {}) {
|
|
2810
|
+
const runtime = this.runtime;
|
|
2811
|
+
if (!runtime?.adapter) {
|
|
2812
|
+
return { trajectories: [], total: 0, offset: 0, limit: 50 };
|
|
116
2813
|
}
|
|
117
|
-
|
|
2814
|
+
const offset = Math.max(0, options.offset ?? 0);
|
|
2815
|
+
const limit = Math.min(500, Math.max(1, options.limit ?? 50));
|
|
2816
|
+
const whereClauses = [];
|
|
2817
|
+
if (options.status) {
|
|
2818
|
+
whereClauses.push(`status = ${sqlLiteral(options.status)}`);
|
|
2819
|
+
}
|
|
2820
|
+
if (options.source) {
|
|
2821
|
+
whereClauses.push(`source = ${sqlLiteral(options.source)}`);
|
|
2822
|
+
}
|
|
2823
|
+
if (options.scenarioId) {
|
|
2824
|
+
whereClauses.push(`scenario_id = ${sqlLiteral(options.scenarioId)}`);
|
|
2825
|
+
}
|
|
2826
|
+
if (options.batchId) {
|
|
2827
|
+
whereClauses.push(`batch_id = ${sqlLiteral(options.batchId)}`);
|
|
2828
|
+
}
|
|
2829
|
+
if (options.isTrainingData !== undefined) {
|
|
2830
|
+
whereClauses.push(`is_training_data = ${options.isTrainingData}`);
|
|
2831
|
+
}
|
|
2832
|
+
if (options.startDate) {
|
|
2833
|
+
whereClauses.push(`created_at >= ${sqlLiteral(options.startDate)}::timestamptz`);
|
|
2834
|
+
}
|
|
2835
|
+
if (options.endDate) {
|
|
2836
|
+
whereClauses.push(`created_at <= ${sqlLiteral(options.endDate)}::timestamptz`);
|
|
2837
|
+
}
|
|
2838
|
+
if (options.search) {
|
|
2839
|
+
const escaped = options.search.replace(/'/g, "''").replace(/%/g, "\\%");
|
|
2840
|
+
whereClauses.push(`(
|
|
2841
|
+
id ILIKE '%${escaped}%' OR
|
|
2842
|
+
agent_id ILIKE '%${escaped}%' OR
|
|
2843
|
+
source ILIKE '%${escaped}%' OR
|
|
2844
|
+
scenario_id ILIKE '%${escaped}%'
|
|
2845
|
+
)`);
|
|
2846
|
+
}
|
|
2847
|
+
const whereClause = whereClauses.length > 0 ? `WHERE ${whereClauses.join(" AND ")}` : "";
|
|
2848
|
+
const countResult = await this.executeRawSql(`SELECT count(*)::int AS total FROM trajectories ${whereClause}`);
|
|
2849
|
+
const total = asNumber(pickCell(countResult.rows[0] ?? {}, "total")) ?? 0;
|
|
2850
|
+
const rowsResult = await this.executeRawSql(`
|
|
2851
|
+
SELECT
|
|
2852
|
+
id, agent_id, source, status, start_time, end_time, duration_ms,
|
|
2853
|
+
step_count, llm_call_count, total_prompt_tokens, total_completion_tokens,
|
|
2854
|
+
total_reward, scenario_id, batch_id, created_at
|
|
2855
|
+
FROM trajectories
|
|
2856
|
+
${whereClause}
|
|
2857
|
+
ORDER BY created_at DESC
|
|
2858
|
+
LIMIT ${limit} OFFSET ${offset}
|
|
2859
|
+
`);
|
|
2860
|
+
const trajectories = rowsResult.rows.map((row) => {
|
|
2861
|
+
const status = asString(pickCell(row, "status")) ?? "completed";
|
|
2862
|
+
const rawLlmCallCount = asNumber(pickCell(row, "llm_call_count")) ?? 0;
|
|
2863
|
+
const llmCallCount = status === "active" ? rawLlmCallCount : Math.max(1, rawLlmCallCount);
|
|
2864
|
+
return {
|
|
2865
|
+
id: asString(pickCell(row, "id")) ?? "",
|
|
2866
|
+
agentId: asString(pickCell(row, "agent_id")) ?? "",
|
|
2867
|
+
source: asString(pickCell(row, "source")) ?? "chat",
|
|
2868
|
+
status,
|
|
2869
|
+
startTime: asNumber(pickCell(row, "start_time")) ?? 0,
|
|
2870
|
+
endTime: asNumber(pickCell(row, "end_time")),
|
|
2871
|
+
durationMs: asNumber(pickCell(row, "duration_ms")),
|
|
2872
|
+
stepCount: asNumber(pickCell(row, "step_count")) ?? 0,
|
|
2873
|
+
llmCallCount,
|
|
2874
|
+
totalPromptTokens: asNumber(pickCell(row, "total_prompt_tokens")) ?? 0,
|
|
2875
|
+
totalCompletionTokens: asNumber(pickCell(row, "total_completion_tokens")) ?? 0,
|
|
2876
|
+
totalReward: asNumber(pickCell(row, "total_reward")) ?? 0,
|
|
2877
|
+
scenarioId: asString(pickCell(row, "scenario_id")),
|
|
2878
|
+
batchId: asString(pickCell(row, "batch_id")),
|
|
2879
|
+
createdAt: asIsoString(pickCell(row, "created_at"))
|
|
2880
|
+
};
|
|
2881
|
+
});
|
|
2882
|
+
return { trajectories, total, offset, limit };
|
|
118
2883
|
}
|
|
119
|
-
|
|
120
|
-
|
|
2884
|
+
async getTrajectoryDetail(trajectoryId) {
|
|
2885
|
+
const runtime = this.runtime;
|
|
2886
|
+
if (!runtime?.adapter)
|
|
2887
|
+
return null;
|
|
2888
|
+
const safeId = trajectoryId.replace(/'/g, "''");
|
|
2889
|
+
const result = await this.executeRawSql(`SELECT * FROM trajectories WHERE id = '${safeId}' LIMIT 1`);
|
|
2890
|
+
if (result.rows.length === 0)
|
|
2891
|
+
return null;
|
|
2892
|
+
const row = result.rows[0];
|
|
2893
|
+
const trajectory = this.rowToTrajectory(row);
|
|
2894
|
+
const status = this.normalizeTrajectoryStatus(asString(pickCell(row, "status")));
|
|
2895
|
+
if (status !== "active") {
|
|
2896
|
+
const inserted = this.ensureAtLeastOneLlmCall(trajectory, "backfill");
|
|
2897
|
+
if (inserted) {
|
|
2898
|
+
await this.withTrajectoryWriteLock(trajectoryId, async () => {
|
|
2899
|
+
await this.persistTrajectory(trajectoryId, trajectory, status);
|
|
2900
|
+
});
|
|
2901
|
+
}
|
|
2902
|
+
}
|
|
2903
|
+
return trajectory;
|
|
121
2904
|
}
|
|
122
|
-
|
|
123
|
-
const
|
|
124
|
-
if (!
|
|
125
|
-
|
|
126
|
-
|
|
2905
|
+
async getStats() {
|
|
2906
|
+
const runtime = this.runtime;
|
|
2907
|
+
if (!runtime?.adapter) {
|
|
2908
|
+
return {
|
|
2909
|
+
totalTrajectories: 0,
|
|
2910
|
+
totalSteps: 0,
|
|
2911
|
+
totalLlmCalls: 0,
|
|
2912
|
+
totalPromptTokens: 0,
|
|
2913
|
+
totalCompletionTokens: 0,
|
|
2914
|
+
averageDurationMs: 0,
|
|
2915
|
+
averageReward: 0,
|
|
2916
|
+
bySource: {},
|
|
2917
|
+
byStatus: {},
|
|
2918
|
+
byScenario: {}
|
|
2919
|
+
};
|
|
127
2920
|
}
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
2921
|
+
const statsResult = await this.executeRawSql(`
|
|
2922
|
+
SELECT
|
|
2923
|
+
count(*)::int AS total_trajectories,
|
|
2924
|
+
COALESCE(sum(step_count), 0)::int AS total_steps,
|
|
2925
|
+
COALESCE(sum(llm_call_count), 0)::int AS total_llm_calls,
|
|
2926
|
+
COALESCE(sum(total_prompt_tokens), 0)::int AS total_prompt_tokens,
|
|
2927
|
+
COALESCE(sum(total_completion_tokens), 0)::int AS total_completion_tokens,
|
|
2928
|
+
COALESCE(avg(duration_ms), 0)::int AS avg_duration_ms,
|
|
2929
|
+
COALESCE(avg(total_reward), 0)::real AS avg_reward
|
|
2930
|
+
FROM trajectories
|
|
2931
|
+
`);
|
|
2932
|
+
const sourceResult = await this.executeRawSql(`
|
|
2933
|
+
SELECT source, count(*)::int AS cnt
|
|
2934
|
+
FROM trajectories
|
|
2935
|
+
GROUP BY source
|
|
2936
|
+
`);
|
|
2937
|
+
const statusResult = await this.executeRawSql(`
|
|
2938
|
+
SELECT status, count(*)::int AS cnt
|
|
2939
|
+
FROM trajectories
|
|
2940
|
+
GROUP BY status
|
|
2941
|
+
`);
|
|
2942
|
+
const scenarioResult = await this.executeRawSql(`
|
|
2943
|
+
SELECT scenario_id, count(*)::int AS cnt
|
|
2944
|
+
FROM trajectories
|
|
2945
|
+
WHERE scenario_id IS NOT NULL
|
|
2946
|
+
GROUP BY scenario_id
|
|
2947
|
+
`);
|
|
2948
|
+
const stats = statsResult.rows[0] ?? {};
|
|
2949
|
+
const bySource = {};
|
|
2950
|
+
const byStatus = {};
|
|
2951
|
+
const byScenario = {};
|
|
2952
|
+
for (const row of sourceResult.rows) {
|
|
2953
|
+
const source = asString(pickCell(row, "source"));
|
|
2954
|
+
const cnt = asNumber(pickCell(row, "cnt"));
|
|
2955
|
+
if (source && cnt !== null)
|
|
2956
|
+
bySource[source] = cnt;
|
|
2957
|
+
}
|
|
2958
|
+
for (const row of statusResult.rows) {
|
|
2959
|
+
const status = asString(pickCell(row, "status"));
|
|
2960
|
+
const cnt = asNumber(pickCell(row, "cnt"));
|
|
2961
|
+
if (status && cnt !== null)
|
|
2962
|
+
byStatus[status] = cnt;
|
|
2963
|
+
}
|
|
2964
|
+
for (const row of scenarioResult.rows) {
|
|
2965
|
+
const scenario = asString(pickCell(row, "scenario_id"));
|
|
2966
|
+
const cnt = asNumber(pickCell(row, "cnt"));
|
|
2967
|
+
if (scenario && cnt !== null)
|
|
2968
|
+
byScenario[scenario] = cnt;
|
|
132
2969
|
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
2970
|
+
return {
|
|
2971
|
+
totalTrajectories: asNumber(pickCell(stats, "total_trajectories")) ?? 0,
|
|
2972
|
+
totalSteps: asNumber(pickCell(stats, "total_steps")) ?? 0,
|
|
2973
|
+
totalLlmCalls: asNumber(pickCell(stats, "total_llm_calls")) ?? 0,
|
|
2974
|
+
totalPromptTokens: asNumber(pickCell(stats, "total_prompt_tokens")) ?? 0,
|
|
2975
|
+
totalCompletionTokens: asNumber(pickCell(stats, "total_completion_tokens")) ?? 0,
|
|
2976
|
+
averageDurationMs: asNumber(pickCell(stats, "avg_duration_ms")) ?? 0,
|
|
2977
|
+
averageReward: asNumber(pickCell(stats, "avg_reward")) ?? 0,
|
|
2978
|
+
bySource,
|
|
2979
|
+
byStatus,
|
|
2980
|
+
byScenario
|
|
137
2981
|
};
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
2982
|
+
}
|
|
2983
|
+
async deleteTrajectories(trajectoryIds) {
|
|
2984
|
+
const runtime = this.runtime;
|
|
2985
|
+
if (!runtime?.adapter)
|
|
2986
|
+
return 0;
|
|
2987
|
+
if (trajectoryIds.length === 0)
|
|
2988
|
+
return 0;
|
|
2989
|
+
const ids = trajectoryIds.map(sqlLiteral).join(", ");
|
|
2990
|
+
const result = await this.executeRawSql(`DELETE FROM trajectories WHERE id IN (${ids}) RETURNING id`);
|
|
2991
|
+
return result.rows.length;
|
|
2992
|
+
}
|
|
2993
|
+
async clearAllTrajectories() {
|
|
2994
|
+
const runtime = this.runtime;
|
|
2995
|
+
if (!runtime?.adapter)
|
|
2996
|
+
return 0;
|
|
2997
|
+
const countResult = await this.executeRawSql(`SELECT count(*)::int AS cnt FROM trajectories`);
|
|
2998
|
+
const count2 = asNumber(pickCell(countResult.rows[0] ?? {}, "cnt")) ?? 0;
|
|
2999
|
+
await this.executeRawSql(`DELETE FROM trajectories`);
|
|
3000
|
+
return count2;
|
|
3001
|
+
}
|
|
3002
|
+
sanitizeZipFolderName(value) {
|
|
3003
|
+
const sanitized = value.trim().replace(/[^a-zA-Z0-9._-]+/g, "_").replace(/^_+|_+$/g, "");
|
|
3004
|
+
return sanitized || "trajectory";
|
|
3005
|
+
}
|
|
3006
|
+
redactTrajectoryPrompts(trajectory) {
|
|
3007
|
+
return {
|
|
3008
|
+
...trajectory,
|
|
3009
|
+
steps: trajectory.steps.map((step) => ({
|
|
3010
|
+
...step,
|
|
3011
|
+
llmCalls: step.llmCalls.map((call) => ({
|
|
3012
|
+
...call,
|
|
3013
|
+
systemPrompt: "[redacted]",
|
|
3014
|
+
userPrompt: "[redacted]",
|
|
3015
|
+
response: "[redacted]"
|
|
3016
|
+
}))
|
|
3017
|
+
}))
|
|
3018
|
+
};
|
|
3019
|
+
}
|
|
3020
|
+
buildZipSummary(trajectory) {
|
|
3021
|
+
const finalStatus = trajectory.metrics?.finalStatus ?? "completed";
|
|
3022
|
+
const normalizedEndTime = typeof trajectory.endTime === "number" && trajectory.endTime > 0 ? trajectory.endTime : null;
|
|
3023
|
+
const status = finalStatus === "timeout" || finalStatus === "terminated" || finalStatus === "error" ? "error" : finalStatus === "completed" ? "completed" : normalizedEndTime ? "completed" : "active";
|
|
3024
|
+
let llmCallCount = 0;
|
|
3025
|
+
let providerAccessCount = 0;
|
|
3026
|
+
let totalPromptTokens = 0;
|
|
3027
|
+
let totalCompletionTokens = 0;
|
|
3028
|
+
for (const step of trajectory.steps) {
|
|
3029
|
+
providerAccessCount += step.providerAccesses.length;
|
|
3030
|
+
llmCallCount += step.llmCalls.length;
|
|
3031
|
+
for (const call of step.llmCalls) {
|
|
3032
|
+
totalPromptTokens += call.promptTokens ?? 0;
|
|
3033
|
+
totalCompletionTokens += call.completionTokens ?? 0;
|
|
3034
|
+
}
|
|
147
3035
|
}
|
|
148
|
-
|
|
3036
|
+
const metadata = trajectory.metadata ?? {};
|
|
3037
|
+
const asNullableString = (value) => typeof value === "string" ? value : null;
|
|
3038
|
+
const source = typeof metadata.source === "string" ? metadata.source : "chat";
|
|
3039
|
+
const normalizedDurationMs = status === "active" ? null : typeof trajectory.durationMs === "number" ? trajectory.durationMs : null;
|
|
3040
|
+
const updatedAtMs = normalizedEndTime ?? (trajectory.startTime || Date.now());
|
|
3041
|
+
return {
|
|
3042
|
+
id: trajectory.trajectoryId,
|
|
3043
|
+
agentId: trajectory.agentId,
|
|
3044
|
+
roomId: asNullableString(metadata.roomId),
|
|
3045
|
+
entityId: asNullableString(metadata.entityId),
|
|
3046
|
+
conversationId: asNullableString(metadata.conversationId),
|
|
3047
|
+
source,
|
|
3048
|
+
status,
|
|
3049
|
+
startTime: trajectory.startTime,
|
|
3050
|
+
endTime: normalizedEndTime,
|
|
3051
|
+
durationMs: normalizedDurationMs,
|
|
3052
|
+
llmCallCount,
|
|
3053
|
+
providerAccessCount,
|
|
3054
|
+
totalPromptTokens,
|
|
3055
|
+
totalCompletionTokens,
|
|
3056
|
+
metadata,
|
|
3057
|
+
createdAt: new Date(trajectory.startTime).toISOString(),
|
|
3058
|
+
updatedAt: new Date(updatedAtMs).toISOString()
|
|
3059
|
+
};
|
|
149
3060
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
if (
|
|
153
|
-
|
|
154
|
-
|
|
3061
|
+
async exportTrajectoriesZip(options = {}) {
|
|
3062
|
+
let targetIds = Array.isArray(options.trajectoryIds) ? options.trajectoryIds.filter((id) => typeof id === "string" && id.trim().length > 0) : [];
|
|
3063
|
+
if (targetIds.length === 0) {
|
|
3064
|
+
const list = await this.listTrajectories({
|
|
3065
|
+
limit: 500,
|
|
3066
|
+
startDate: options.startDate,
|
|
3067
|
+
endDate: options.endDate,
|
|
3068
|
+
scenarioId: options.scenarioId,
|
|
3069
|
+
batchId: options.batchId
|
|
3070
|
+
});
|
|
3071
|
+
targetIds = list.trajectories.map((trajectory) => trajectory.id);
|
|
3072
|
+
}
|
|
3073
|
+
const entries = [];
|
|
3074
|
+
const manifestRows = [];
|
|
3075
|
+
for (const trajectoryId of targetIds) {
|
|
3076
|
+
const detail = await this.getTrajectoryDetail(trajectoryId);
|
|
3077
|
+
if (!detail)
|
|
3078
|
+
continue;
|
|
3079
|
+
const exportTrajectory = options.includePrompts === false ? this.redactTrajectoryPrompts(detail) : detail;
|
|
3080
|
+
const summary = this.buildZipSummary(exportTrajectory);
|
|
3081
|
+
const folderName = this.sanitizeZipFolderName(trajectoryId);
|
|
3082
|
+
entries.push({
|
|
3083
|
+
name: `${folderName}/trajectory.json`,
|
|
3084
|
+
data: JSON.stringify(exportTrajectory, null, 2)
|
|
3085
|
+
});
|
|
3086
|
+
entries.push({
|
|
3087
|
+
name: `${folderName}/summary.json`,
|
|
3088
|
+
data: JSON.stringify(summary, null, 2)
|
|
3089
|
+
});
|
|
3090
|
+
manifestRows.push({
|
|
3091
|
+
trajectoryId,
|
|
3092
|
+
folder: folderName,
|
|
3093
|
+
createdAt: summary.createdAt
|
|
3094
|
+
});
|
|
155
3095
|
}
|
|
156
|
-
|
|
3096
|
+
entries.unshift({
|
|
3097
|
+
name: "manifest.json",
|
|
3098
|
+
data: JSON.stringify({
|
|
3099
|
+
exportedAt: new Date().toISOString(),
|
|
3100
|
+
trajectories: manifestRows
|
|
3101
|
+
}, null, 2)
|
|
3102
|
+
});
|
|
3103
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
3104
|
+
return {
|
|
3105
|
+
filename: `trajectories-${timestamp}.zip`,
|
|
3106
|
+
entries
|
|
3107
|
+
};
|
|
157
3108
|
}
|
|
158
|
-
async
|
|
159
|
-
const
|
|
160
|
-
if (!
|
|
161
|
-
|
|
162
|
-
|
|
3109
|
+
async exportTrajectories(options) {
|
|
3110
|
+
const runtime = this.runtime;
|
|
3111
|
+
if (!runtime?.adapter) {
|
|
3112
|
+
throw new Error("Database not available");
|
|
3113
|
+
}
|
|
3114
|
+
const whereClauses = [];
|
|
3115
|
+
if (options.trajectoryIds && options.trajectoryIds.length > 0) {
|
|
3116
|
+
const ids = options.trajectoryIds.map(sqlLiteral).join(", ");
|
|
3117
|
+
whereClauses.push(`id IN (${ids})`);
|
|
3118
|
+
}
|
|
3119
|
+
if (options.startDate) {
|
|
3120
|
+
whereClauses.push(`created_at >= ${sqlLiteral(options.startDate)}::timestamptz`);
|
|
3121
|
+
}
|
|
3122
|
+
if (options.endDate) {
|
|
3123
|
+
whereClauses.push(`created_at <= ${sqlLiteral(options.endDate)}::timestamptz`);
|
|
3124
|
+
}
|
|
3125
|
+
if (options.scenarioId) {
|
|
3126
|
+
whereClauses.push(`scenario_id = ${sqlLiteral(options.scenarioId)}`);
|
|
3127
|
+
}
|
|
3128
|
+
if (options.batchId) {
|
|
3129
|
+
whereClauses.push(`batch_id = ${sqlLiteral(options.batchId)}`);
|
|
163
3130
|
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
if (
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
3131
|
+
const whereClause = whereClauses.length > 0 ? `WHERE ${whereClauses.join(" AND ")}` : "";
|
|
3132
|
+
const result = await this.executeRawSql(`SELECT * FROM trajectories ${whereClause} ORDER BY created_at DESC`);
|
|
3133
|
+
const trajectories = result.rows.map((row) => this.rowToTrajectory(row));
|
|
3134
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
3135
|
+
if (options.format === "csv") {
|
|
3136
|
+
const lines = [
|
|
3137
|
+
"id,agent_id,source,status,start_time,end_time,duration_ms,step_count,llm_call_count,total_reward,scenario_id"
|
|
3138
|
+
];
|
|
3139
|
+
for (const t of trajectories) {
|
|
3140
|
+
lines.push([
|
|
3141
|
+
t.trajectoryId,
|
|
3142
|
+
t.agentId,
|
|
3143
|
+
t.metadata.source ?? "chat",
|
|
3144
|
+
t.metrics.finalStatus,
|
|
3145
|
+
t.startTime,
|
|
3146
|
+
t.endTime,
|
|
3147
|
+
t.durationMs,
|
|
3148
|
+
t.steps.length,
|
|
3149
|
+
t.steps.reduce((sum2, s) => sum2 + s.llmCalls.length, 0),
|
|
3150
|
+
t.totalReward,
|
|
3151
|
+
t.scenarioId ?? ""
|
|
3152
|
+
].join(","));
|
|
3153
|
+
}
|
|
3154
|
+
return {
|
|
3155
|
+
data: lines.join(`
|
|
3156
|
+
`),
|
|
3157
|
+
filename: `trajectories-${timestamp}.csv`,
|
|
3158
|
+
mimeType: "text/csv"
|
|
172
3159
|
};
|
|
173
3160
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
3161
|
+
let exportData = trajectories;
|
|
3162
|
+
if (!options.includePrompts) {
|
|
3163
|
+
exportData = trajectories.map((trajectory) => this.redactTrajectoryPrompts(trajectory));
|
|
3164
|
+
}
|
|
3165
|
+
return {
|
|
3166
|
+
data: JSON.stringify(exportData, null, 2),
|
|
3167
|
+
filename: `trajectories-${timestamp}.json`,
|
|
3168
|
+
mimeType: "application/json"
|
|
3169
|
+
};
|
|
178
3170
|
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
if (
|
|
182
|
-
|
|
3171
|
+
rowToTrajectory(row) {
|
|
3172
|
+
const parseJson = (cell, fallback) => {
|
|
3173
|
+
if (typeof cell === "string") {
|
|
3174
|
+
try {
|
|
3175
|
+
return JSON.parse(cell);
|
|
3176
|
+
} catch {
|
|
3177
|
+
return fallback;
|
|
3178
|
+
}
|
|
183
3179
|
}
|
|
184
|
-
|
|
3180
|
+
if (typeof cell === "object" && cell !== null && !Array.isArray(cell)) {
|
|
3181
|
+
return cell;
|
|
3182
|
+
}
|
|
3183
|
+
return fallback;
|
|
3184
|
+
};
|
|
3185
|
+
return {
|
|
3186
|
+
trajectoryId: asString(pickCell(row, "id")) ?? "",
|
|
3187
|
+
agentId: asString(pickCell(row, "agent_id")) ?? "",
|
|
3188
|
+
startTime: asNumber(pickCell(row, "start_time")) ?? 0,
|
|
3189
|
+
endTime: asNumber(pickCell(row, "end_time")) ?? 0,
|
|
3190
|
+
durationMs: asNumber(pickCell(row, "duration_ms")) ?? 0,
|
|
3191
|
+
scenarioId: asString(pickCell(row, "scenario_id")) ?? undefined,
|
|
3192
|
+
episodeId: asString(pickCell(row, "episode_id")) ?? undefined,
|
|
3193
|
+
batchId: asString(pickCell(row, "batch_id")) ?? undefined,
|
|
3194
|
+
groupIndex: asNumber(pickCell(row, "group_index")) ?? undefined,
|
|
3195
|
+
steps: parseJson(pickCell(row, "steps_json", "steps"), []),
|
|
3196
|
+
totalReward: asNumber(pickCell(row, "total_reward")) ?? 0,
|
|
3197
|
+
rewardComponents: parseJson(pickCell(row, "reward_components_json", "reward_components"), { environmentReward: 0 }),
|
|
3198
|
+
metrics: parseJson(pickCell(row, "metrics_json", "metrics"), {
|
|
3199
|
+
episodeLength: 0,
|
|
3200
|
+
finalStatus: "completed"
|
|
3201
|
+
}),
|
|
3202
|
+
metadata: parseJson(pickCell(row, "metadata_json", "metadata"), {})
|
|
3203
|
+
};
|
|
3204
|
+
}
|
|
3205
|
+
getActiveTrajectory(trajectoryId) {
|
|
185
3206
|
return null;
|
|
186
3207
|
}
|
|
3208
|
+
getCurrentStepId(trajectoryId) {
|
|
3209
|
+
return this.activeStepIds.get(trajectoryId) || null;
|
|
3210
|
+
}
|
|
3211
|
+
getProviderAccessLogs() {
|
|
3212
|
+
return [];
|
|
3213
|
+
}
|
|
3214
|
+
getLlmCallLogs() {
|
|
3215
|
+
return [];
|
|
3216
|
+
}
|
|
3217
|
+
}
|
|
3218
|
+
function extractInsightsFromResponse(response, purpose) {
|
|
3219
|
+
const insights = [];
|
|
3220
|
+
const decisionPattern = /DECISION:\s*(.+?)(?:\n|$)/gi;
|
|
3221
|
+
let match;
|
|
3222
|
+
match = decisionPattern.exec(response);
|
|
3223
|
+
while (match !== null) {
|
|
3224
|
+
insights.push(match[1].trim());
|
|
3225
|
+
match = decisionPattern.exec(response);
|
|
3226
|
+
}
|
|
3227
|
+
const keyDecisionPattern = /"keyDecision"\s*:\s*"([^"]+)"/g;
|
|
3228
|
+
match = keyDecisionPattern.exec(response);
|
|
3229
|
+
while (match !== null) {
|
|
3230
|
+
insights.push(match[1].trim());
|
|
3231
|
+
match = keyDecisionPattern.exec(response);
|
|
3232
|
+
}
|
|
3233
|
+
if ((purpose === "turn-complete" || purpose === "coordination") && insights.length === 0) {
|
|
3234
|
+
const reasoningMatch = response.match(/"reasoning"\s*:\s*"([^"]{20,200})"/);
|
|
3235
|
+
if (reasoningMatch)
|
|
3236
|
+
insights.push(reasoningMatch[1].trim());
|
|
3237
|
+
}
|
|
3238
|
+
return insights;
|
|
3239
|
+
}
|
|
3240
|
+
function readOrchestratorTrajectoryContext(runtime) {
|
|
3241
|
+
if (!runtime || typeof runtime !== "object")
|
|
3242
|
+
return;
|
|
3243
|
+
const ctx = runtime.__orchestratorTrajectoryCtx;
|
|
3244
|
+
if (!ctx || typeof ctx !== "object")
|
|
3245
|
+
return;
|
|
3246
|
+
const candidate = ctx;
|
|
3247
|
+
if (candidate.source !== "orchestrator" || typeof candidate.decisionType !== "string")
|
|
3248
|
+
return;
|
|
3249
|
+
return candidate;
|
|
3250
|
+
}
|
|
3251
|
+
function isNumericVectorString(value) {
|
|
3252
|
+
const trimmed = value.trim();
|
|
3253
|
+
if (trimmed === "[array]")
|
|
3254
|
+
return true;
|
|
3255
|
+
if (!trimmed.startsWith("[") || !trimmed.endsWith("]"))
|
|
3256
|
+
return false;
|
|
3257
|
+
const inner = trimmed.slice(1, -1).trim();
|
|
3258
|
+
if (!inner)
|
|
3259
|
+
return false;
|
|
3260
|
+
const parts = inner.split(",").map((part) => part.trim()).filter((part) => part.length > 0);
|
|
3261
|
+
if (parts.length < 8)
|
|
3262
|
+
return false;
|
|
3263
|
+
const sampleSize = Math.min(parts.length, 16);
|
|
3264
|
+
for (let i = 0;i < sampleSize; i += 1) {
|
|
3265
|
+
const numeric = Number(parts[i]);
|
|
3266
|
+
if (!Number.isFinite(numeric))
|
|
3267
|
+
return false;
|
|
3268
|
+
}
|
|
3269
|
+
return true;
|
|
3270
|
+
}
|
|
3271
|
+
function shouldSuppressNoInputEmbeddingCall(params) {
|
|
3272
|
+
const model = String(params.model || "").toLowerCase();
|
|
3273
|
+
const actionType = String(params.actionType || "").toLowerCase();
|
|
3274
|
+
const purpose = String(params.purpose || "").toLowerCase();
|
|
3275
|
+
const isEmbedding = model.includes("embed") || actionType.includes("embed") || purpose.includes("embed");
|
|
3276
|
+
if (!isEmbedding)
|
|
3277
|
+
return false;
|
|
3278
|
+
const userPrompt = String(params.userPrompt ?? params.input ?? "").trim();
|
|
3279
|
+
if (userPrompt.length > 0)
|
|
3280
|
+
return false;
|
|
3281
|
+
const response = String(params.response || "");
|
|
3282
|
+
if (!response.trim())
|
|
3283
|
+
return true;
|
|
3284
|
+
return isNumericVectorString(response);
|
|
3285
|
+
}
|
|
3286
|
+
function shouldRunObservationExtraction(runtime) {
|
|
3287
|
+
if (typeof runtime.getSetting === "function") {
|
|
3288
|
+
const setting = runtime.getSetting("TRAJECTORY_OBSERVATION_EXTRACTION");
|
|
3289
|
+
if (setting === "true")
|
|
3290
|
+
return true;
|
|
3291
|
+
if (setting === "false")
|
|
3292
|
+
return false;
|
|
3293
|
+
}
|
|
3294
|
+
const hasReflection = Array.isArray(runtime.evaluators) && runtime.evaluators.some((e) => e.name === "REFLECTION" || e.name === "RELATIONSHIP_EXTRACTION");
|
|
3295
|
+
return !hasReflection;
|
|
187
3296
|
}
|
|
188
|
-
|
|
189
3297
|
// action-interceptor.ts
|
|
190
|
-
import { logger as
|
|
3298
|
+
import { logger as logger3 } from "@elizaos/core";
|
|
191
3299
|
var trajectoryContexts = new WeakMap;
|
|
192
3300
|
function setTrajectoryContext(runtime, trajectoryId, trajectoryLogger) {
|
|
193
3301
|
trajectoryContexts.set(runtime, { trajectoryId, logger: trajectoryLogger });
|
|
194
3302
|
}
|
|
195
|
-
function
|
|
3303
|
+
function getTrajectoryContext2(runtime) {
|
|
196
3304
|
return trajectoryContexts.get(runtime) || null;
|
|
197
3305
|
}
|
|
198
3306
|
function clearTrajectoryContext(runtime) {
|
|
@@ -203,7 +3311,7 @@ function wrapActionWithLogging(action, _trajectoryLogger) {
|
|
|
203
3311
|
return {
|
|
204
3312
|
...action,
|
|
205
3313
|
handler: async (runtime, message, state, options, callback) => {
|
|
206
|
-
const context =
|
|
3314
|
+
const context = getTrajectoryContext2(runtime);
|
|
207
3315
|
if (!context) {
|
|
208
3316
|
const result = await originalHandler(runtime, message, state, options, callback);
|
|
209
3317
|
return result ?? undefined;
|
|
@@ -211,7 +3319,7 @@ function wrapActionWithLogging(action, _trajectoryLogger) {
|
|
|
211
3319
|
const { trajectoryId, logger: loggerService } = context;
|
|
212
3320
|
const stepId = loggerService.getCurrentStepId(trajectoryId);
|
|
213
3321
|
if (!stepId) {
|
|
214
|
-
|
|
3322
|
+
logger3.warn({ action: action.name, trajectoryId }, "No active step for action execution");
|
|
215
3323
|
const result = await originalHandler(runtime, message, state, options, callback);
|
|
216
3324
|
return result ?? undefined;
|
|
217
3325
|
}
|
|
@@ -231,7 +3339,7 @@ function wrapActionWithLogging(action, _trajectoryLogger) {
|
|
|
231
3339
|
};
|
|
232
3340
|
const errorHandler = (err) => {
|
|
233
3341
|
const error = err instanceof Error ? err.message : typeof err === "string" ? err : err.message || String(err);
|
|
234
|
-
|
|
3342
|
+
logger3.error({ action: action.name, trajectoryId, error }, "Action execution failed");
|
|
235
3343
|
const stateSnapshot = state ? JSON.parse(JSON.stringify(state)) : null;
|
|
236
3344
|
loggerService.completeStep(trajectoryId, stepId, {
|
|
237
3345
|
actionType: action.name,
|
|
@@ -274,7 +3382,7 @@ function wrapPluginActions(plugin, trajectoryLogger) {
|
|
|
274
3382
|
function logLLMCallFromAction(actionContext, trajectoryLogger, trajectoryId) {
|
|
275
3383
|
const stepId = trajectoryLogger.getCurrentStepId(trajectoryId);
|
|
276
3384
|
if (!stepId) {
|
|
277
|
-
|
|
3385
|
+
logger3.warn({ trajectoryId }, "No active step for LLM call from action");
|
|
278
3386
|
return;
|
|
279
3387
|
}
|
|
280
3388
|
trajectoryLogger.logLLMCall(stepId, {
|
|
@@ -295,7 +3403,7 @@ function logLLMCallFromAction(actionContext, trajectoryLogger, trajectoryId) {
|
|
|
295
3403
|
function logProviderFromAction(actionContext, trajectoryLogger, trajectoryId) {
|
|
296
3404
|
const stepId = trajectoryLogger.getCurrentStepId(trajectoryId);
|
|
297
3405
|
if (!stepId) {
|
|
298
|
-
|
|
3406
|
+
logger3.warn({ trajectoryId }, "No active step for provider access from action");
|
|
299
3407
|
return;
|
|
300
3408
|
}
|
|
301
3409
|
trajectoryLogger.logProviderAccess(stepId, {
|
|
@@ -310,14 +3418,14 @@ function wrapProviderWithLogging(provider, _trajectoryLogger) {
|
|
|
310
3418
|
return {
|
|
311
3419
|
...provider,
|
|
312
3420
|
get: async (runtime, message, state) => {
|
|
313
|
-
const context =
|
|
3421
|
+
const context = getTrajectoryContext2(runtime);
|
|
314
3422
|
if (!context) {
|
|
315
3423
|
return originalGet?.(runtime, message, state) || { text: "" };
|
|
316
3424
|
}
|
|
317
3425
|
const { trajectoryId, logger: loggerService } = context;
|
|
318
3426
|
const stepId = loggerService.getCurrentStepId(trajectoryId);
|
|
319
3427
|
if (!stepId) {
|
|
320
|
-
|
|
3428
|
+
logger3.warn({ provider: provider.name, trajectoryId }, "No active step for provider access");
|
|
321
3429
|
return originalGet?.(runtime, message, state) || { text: "" };
|
|
322
3430
|
}
|
|
323
3431
|
const result = await originalGet?.(runtime, message, state) || { text: "" };
|
|
@@ -519,14 +3627,14 @@ function toARTJSONL(trajectory) {
|
|
|
519
3627
|
return JSON.stringify(toARTTrajectory(trajectory));
|
|
520
3628
|
}
|
|
521
3629
|
function validateARTCompatibility(trajectory) {
|
|
522
|
-
const
|
|
3630
|
+
const errors2 = [];
|
|
523
3631
|
const warnings = [];
|
|
524
3632
|
if (trajectory.steps.length === 0) {
|
|
525
|
-
|
|
3633
|
+
errors2.push("Trajectory has no steps");
|
|
526
3634
|
}
|
|
527
3635
|
for (const [idx, step] of trajectory.steps.entries()) {
|
|
528
3636
|
if (step.llmCalls.length === 0) {
|
|
529
|
-
|
|
3637
|
+
errors2.push(`Step ${idx} has no LLM calls - can't extract messages`);
|
|
530
3638
|
}
|
|
531
3639
|
for (const llmCall of step.llmCalls) {
|
|
532
3640
|
if (!llmCall.userPrompt || llmCall.userPrompt.length < 10) {
|
|
@@ -538,15 +3646,15 @@ function validateARTCompatibility(trajectory) {
|
|
|
538
3646
|
}
|
|
539
3647
|
}
|
|
540
3648
|
if (trajectory.totalReward === undefined || Number.isNaN(trajectory.totalReward)) {
|
|
541
|
-
|
|
3649
|
+
errors2.push("Trajectory has no valid reward");
|
|
542
3650
|
}
|
|
543
3651
|
const artTraj = toARTTrajectory(trajectory);
|
|
544
3652
|
if (artTraj.messages.length < 2) {
|
|
545
3653
|
warnings.push("Trajectory converts to very few messages (< 2)");
|
|
546
3654
|
}
|
|
547
3655
|
return {
|
|
548
|
-
valid:
|
|
549
|
-
errors,
|
|
3656
|
+
valid: errors2.length === 0,
|
|
3657
|
+
errors: errors2,
|
|
550
3658
|
warnings
|
|
551
3659
|
};
|
|
552
3660
|
}
|
|
@@ -642,9 +3750,9 @@ async function buildGameStateFromDB(_trajectoryId) {
|
|
|
642
3750
|
}
|
|
643
3751
|
async function recomputeTrajectoryRewards(_trajectoryIds) {}
|
|
644
3752
|
// integration.ts
|
|
645
|
-
import { logger as
|
|
646
|
-
function startAutonomousTick(trajectoryLogger, context) {
|
|
647
|
-
const trajectoryId = trajectoryLogger.startTrajectory(context.agentId, {
|
|
3753
|
+
import { logger as logger4 } from "@elizaos/core";
|
|
3754
|
+
async function startAutonomousTick(trajectoryLogger, context) {
|
|
3755
|
+
const trajectoryId = await trajectoryLogger.startTrajectory(context.agentId, {
|
|
648
3756
|
scenarioId: context.scenarioId,
|
|
649
3757
|
episodeId: context.episodeId,
|
|
650
3758
|
batchId: context.batchId,
|
|
@@ -658,17 +3766,17 @@ function startAutonomousTick(trajectoryLogger, context) {
|
|
|
658
3766
|
openPositions: 0
|
|
659
3767
|
};
|
|
660
3768
|
trajectoryLogger.startStep(trajectoryId, envState);
|
|
661
|
-
|
|
3769
|
+
logger4.info({ trajectoryId, agentId: context.agentId }, "Started autonomous tick trajectory");
|
|
662
3770
|
return trajectoryId;
|
|
663
3771
|
}
|
|
664
3772
|
async function endAutonomousTick(trajectoryLogger, trajectoryId, status = "completed", finalMetrics) {
|
|
665
3773
|
await trajectoryLogger.endTrajectory(trajectoryId, status, finalMetrics);
|
|
666
|
-
|
|
3774
|
+
logger4.info({ trajectoryId, status }, "Ended autonomous tick trajectory");
|
|
667
3775
|
}
|
|
668
3776
|
async function loggedLLMCall(trajectoryLogger, trajectoryId, options, llmCallFn) {
|
|
669
3777
|
const stepId = trajectoryLogger.getCurrentStepId(trajectoryId);
|
|
670
3778
|
if (!stepId) {
|
|
671
|
-
|
|
3779
|
+
logger4.warn({ trajectoryId }, "No active step for LLM call");
|
|
672
3780
|
const result2 = await llmCallFn();
|
|
673
3781
|
return result2.text;
|
|
674
3782
|
}
|
|
@@ -773,13 +3881,13 @@ class RewardService {
|
|
|
773
3881
|
return (score + 1) / 2;
|
|
774
3882
|
}
|
|
775
3883
|
normalizeScoresForGroup(scores) {
|
|
776
|
-
const
|
|
777
|
-
const
|
|
778
|
-
const range =
|
|
3884
|
+
const min2 = Math.min(...scores);
|
|
3885
|
+
const max2 = Math.max(...scores);
|
|
3886
|
+
const range = max2 - min2;
|
|
779
3887
|
if (range === 0) {
|
|
780
3888
|
return scores.map(() => 0.5);
|
|
781
3889
|
}
|
|
782
|
-
return scores.map((s) => (s -
|
|
3890
|
+
return scores.map((s) => (s - min2) / range);
|
|
783
3891
|
}
|
|
784
3892
|
}
|
|
785
3893
|
function createRewardService(options = {}) {
|
|
@@ -809,16 +3917,18 @@ var trajectoryLoggerPlugin = {
|
|
|
809
3917
|
if (!message || !runtime)
|
|
810
3918
|
return;
|
|
811
3919
|
if (!message.metadata) {
|
|
812
|
-
message.metadata = {
|
|
3920
|
+
message.metadata = {
|
|
3921
|
+
type: "message"
|
|
3922
|
+
};
|
|
813
3923
|
}
|
|
814
3924
|
const meta = message.metadata;
|
|
815
|
-
const
|
|
816
|
-
if (!
|
|
3925
|
+
const logger5 = runtime.getService("trajectory_logger");
|
|
3926
|
+
if (!logger5)
|
|
817
3927
|
return;
|
|
818
3928
|
let trajectoryStepId = crypto.randomUUID();
|
|
819
3929
|
meta.trajectoryStepId = trajectoryStepId;
|
|
820
3930
|
try {
|
|
821
|
-
const trajectoryId = await
|
|
3931
|
+
const trajectoryId = await logger5.startTrajectory(runtime.agentId, {
|
|
822
3932
|
source: source ?? meta.source ?? "chat",
|
|
823
3933
|
metadata: {
|
|
824
3934
|
roomId: message.roomId,
|
|
@@ -830,7 +3940,7 @@ var trajectoryLoggerPlugin = {
|
|
|
830
3940
|
});
|
|
831
3941
|
const normalizedTrajectoryId = typeof trajectoryId === "string" && trajectoryId.trim().length > 0 ? trajectoryId : null;
|
|
832
3942
|
if (normalizedTrajectoryId) {
|
|
833
|
-
const runtimeStepId =
|
|
3943
|
+
const runtimeStepId = logger5.startStep(normalizedTrajectoryId, {
|
|
834
3944
|
timestamp: Date.now(),
|
|
835
3945
|
agentBalance: 0,
|
|
836
3946
|
agentPoints: 0,
|
|
@@ -841,13 +3951,17 @@ var trajectoryLoggerPlugin = {
|
|
|
841
3951
|
trajectoryStepId = normalizedStepId;
|
|
842
3952
|
meta.trajectoryStepId = trajectoryStepId;
|
|
843
3953
|
pendingTrajectoryEndTargetByStepId.set(trajectoryStepId, normalizedTrajectoryId);
|
|
844
|
-
}
|
|
3954
|
+
} else {}
|
|
845
3955
|
if (message.id) {
|
|
846
3956
|
const replyId = createUniqueUuid(runtime, message.id);
|
|
847
3957
|
pendingTrajectoryStepByReplyId.set(replyId, trajectoryStepId);
|
|
848
3958
|
}
|
|
849
3959
|
} catch (err) {
|
|
850
|
-
runtime.logger?.warn({
|
|
3960
|
+
runtime.logger?.warn({
|
|
3961
|
+
err,
|
|
3962
|
+
src: "plugin-trajectory-logger",
|
|
3963
|
+
roomId: message.roomId
|
|
3964
|
+
}, "Failed to start trajectory logging");
|
|
851
3965
|
}
|
|
852
3966
|
}
|
|
853
3967
|
],
|
|
@@ -864,14 +3978,18 @@ var trajectoryLoggerPlugin = {
|
|
|
864
3978
|
}
|
|
865
3979
|
if (!trajectoryStepId)
|
|
866
3980
|
return;
|
|
867
|
-
const
|
|
868
|
-
if (!
|
|
3981
|
+
const logger5 = runtime.getService("trajectory_logger");
|
|
3982
|
+
if (!logger5)
|
|
869
3983
|
return;
|
|
870
3984
|
try {
|
|
871
3985
|
const endTarget = pendingTrajectoryEndTargetByStepId.get(trajectoryStepId) ?? trajectoryStepId;
|
|
872
|
-
await
|
|
3986
|
+
await logger5.endTrajectory(endTarget, "completed");
|
|
873
3987
|
} catch (err) {
|
|
874
|
-
runtime.logger?.warn({
|
|
3988
|
+
runtime.logger?.warn({
|
|
3989
|
+
err,
|
|
3990
|
+
src: "plugin-trajectory-logger",
|
|
3991
|
+
trajectoryStepId
|
|
3992
|
+
}, "Failed to end trajectory logging");
|
|
875
3993
|
}
|
|
876
3994
|
if (inReplyTo) {
|
|
877
3995
|
pendingTrajectoryStepByReplyId.delete(inReplyTo);
|
|
@@ -905,7 +4023,7 @@ export {
|
|
|
905
4023
|
logProviderAccess,
|
|
906
4024
|
logLLMCallFromAction,
|
|
907
4025
|
groupTrajectories,
|
|
908
|
-
getTrajectoryContext,
|
|
4026
|
+
getTrajectoryContext2 as getTrajectoryContext,
|
|
909
4027
|
extractSharedPrefix,
|
|
910
4028
|
exportToHuggingFace,
|
|
911
4029
|
exportGroupedForGRPO,
|
|
@@ -922,4 +4040,4 @@ export {
|
|
|
922
4040
|
RewardService
|
|
923
4041
|
};
|
|
924
4042
|
|
|
925
|
-
//# debugId=
|
|
4043
|
+
//# debugId=07960868DB73CC4E64756E2164756E21
|