@dudousxd/nestjs-agent-store-drizzle 0.34.0 → 0.36.0
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/index.cjs +228 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1082 -19
- package/dist/index.d.ts +1082 -19
- package/dist/index.js +239 -33
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -240,7 +240,7 @@ var agentQueuedMessage = (0, import_sqlite_core.sqliteTable)("agent_queued_messa
|
|
|
240
240
|
]);
|
|
241
241
|
var agentTokenUsage = (0, import_sqlite_core.sqliteTable)("agent_token_usage", {
|
|
242
242
|
id: (0, import_sqlite_core.text)("id").primaryKey(),
|
|
243
|
-
threadId: (0, import_sqlite_core.text)("thread_id").
|
|
243
|
+
threadId: (0, import_sqlite_core.text)("thread_id").references(() => agentThread.id, {
|
|
244
244
|
onDelete: "cascade"
|
|
245
245
|
}),
|
|
246
246
|
actorRef: (0, import_sqlite_core.text)("actor_ref").notNull(),
|
|
@@ -257,13 +257,32 @@ var agentTokenUsage = (0, import_sqlite_core.sqliteTable)("agent_token_usage", {
|
|
|
257
257
|
costUsd: (0, import_sqlite_core.real)("cost_usd"),
|
|
258
258
|
/** Where `cost_usd` came from: `'provider'` (reported) or `'estimate'` (tokens × the price row); null on rows from before it existed (reported). */
|
|
259
259
|
costSource: (0, import_sqlite_core.text)("cost_source").$type(),
|
|
260
|
+
/** The run the row belongs to. */
|
|
261
|
+
runId: (0, import_sqlite_core.text)("run_id"),
|
|
262
|
+
/** What the spend was for: `agent:<name>` for an agent turn, the app's own otherwise; null → `agent`. */
|
|
263
|
+
feature: (0, import_sqlite_core.text)("feature"),
|
|
264
|
+
provider: (0, import_sqlite_core.text)("provider"),
|
|
265
|
+
tenantRef: (0, import_sqlite_core.text)("tenant_ref"),
|
|
266
|
+
/** Units a row bills by when they are not tokens. */
|
|
267
|
+
audioSeconds: (0, import_sqlite_core.real)("audio_seconds"),
|
|
268
|
+
characters: (0, import_sqlite_core.integer)("characters"),
|
|
269
|
+
requests: (0, import_sqlite_core.integer)("requests"),
|
|
270
|
+
/** The caller's own JSON, never read by the library. */
|
|
271
|
+
metadata: (0, import_sqlite_core.text)("metadata", {
|
|
272
|
+
mode: "json"
|
|
273
|
+
}).$type(),
|
|
274
|
+
/** `false` keeps the row out of the agent's quota windows (`recordUsage({ countsTowardsQuota: false })`). */
|
|
275
|
+
countsTowardsQuota: (0, import_sqlite_core.integer)("counts_towards_quota", {
|
|
276
|
+
mode: "boolean"
|
|
277
|
+
}).notNull().default(true),
|
|
260
278
|
createdAt: (0, import_sqlite_core.integer)("created_at", {
|
|
261
279
|
mode: "timestamp_ms"
|
|
262
280
|
}).notNull()
|
|
263
281
|
}, (table) => [
|
|
264
282
|
(0, import_sqlite_core.index)("agent_token_usage_actor_created_idx").on(table.actorRef, table.createdAt),
|
|
265
283
|
(0, import_sqlite_core.index)("agent_token_usage_created_idx").on(table.createdAt),
|
|
266
|
-
(0, import_sqlite_core.index)("agent_token_usage_thread_idx").on(table.threadId)
|
|
284
|
+
(0, import_sqlite_core.index)("agent_token_usage_thread_idx").on(table.threadId),
|
|
285
|
+
(0, import_sqlite_core.index)("agent_token_usage_feature_created_idx").on(table.feature, table.createdAt)
|
|
267
286
|
]);
|
|
268
287
|
var agentGenuiCall = (0, import_sqlite_core.sqliteTable)("agent_genui_call", {
|
|
269
288
|
id: (0, import_sqlite_core.text)("id").primaryKey(),
|
|
@@ -345,7 +364,17 @@ var agentRun = (0, import_sqlite_core.sqliteTable)("agent_run", {
|
|
|
345
364
|
* for a detached child, which outlives its parent's turn and so is paired by nothing in the
|
|
346
365
|
* transcript.
|
|
347
366
|
*/
|
|
348
|
-
parentRunId: (0, import_sqlite_core.text)("parent_run_id")
|
|
367
|
+
parentRunId: (0, import_sqlite_core.text)("parent_run_id"),
|
|
368
|
+
/** Enqueue → body start (ms); null when not read. */
|
|
369
|
+
queueMs: (0, import_sqlite_core.integer)("queue_ms"),
|
|
370
|
+
/** Where the completed run's time went: model and tool totals, counts, and the per-step list. */
|
|
371
|
+
modelMs: (0, import_sqlite_core.integer)("model_ms"),
|
|
372
|
+
toolsMs: (0, import_sqlite_core.integer)("tools_ms"),
|
|
373
|
+
modelCalls: (0, import_sqlite_core.integer)("model_calls"),
|
|
374
|
+
toolCalls: (0, import_sqlite_core.integer)("tool_calls"),
|
|
375
|
+
timings: (0, import_sqlite_core.text)("timings", {
|
|
376
|
+
mode: "json"
|
|
377
|
+
}).$type()
|
|
349
378
|
}, (table) => [
|
|
350
379
|
(0, import_sqlite_core.index)("agent_run_started_idx").on(table.startedAt)
|
|
351
380
|
]);
|
|
@@ -691,7 +720,7 @@ var agentQueuedMessage2 = (0, import_mysql_core.mysqlTable)("agent_queued_messag
|
|
|
691
720
|
]);
|
|
692
721
|
var agentTokenUsage2 = (0, import_mysql_core.mysqlTable)("agent_token_usage", {
|
|
693
722
|
id: key("id").primaryKey(),
|
|
694
|
-
threadId: key("thread_id").
|
|
723
|
+
threadId: key("thread_id").references(() => agentThread2.id, {
|
|
695
724
|
onDelete: "cascade"
|
|
696
725
|
}),
|
|
697
726
|
actorRef: key("actor_ref").notNull(),
|
|
@@ -705,11 +734,28 @@ var agentTokenUsage2 = (0, import_mysql_core.mysqlTable)("agent_token_usage", {
|
|
|
705
734
|
costUsd: (0, import_mysql_core.double)("cost_usd"),
|
|
706
735
|
/** Where `cost_usd` came from: `'provider'` (reported) or `'estimate'` (tokens × the price row); null on rows from before it existed (reported). */
|
|
707
736
|
costSource: key("cost_source").$type(),
|
|
737
|
+
/** The run the row belongs to. */
|
|
738
|
+
runId: key("run_id"),
|
|
739
|
+
/** What the spend was for: `agent:<name>` for an agent turn, the app's own otherwise; null → `agent`. */
|
|
740
|
+
feature: key("feature"),
|
|
741
|
+
provider: key("provider"),
|
|
742
|
+
tenantRef: key("tenant_ref"),
|
|
743
|
+
/** Units a row bills by when they are not tokens. */
|
|
744
|
+
audioSeconds: (0, import_mysql_core.double)("audio_seconds"),
|
|
745
|
+
characters: (0, import_mysql_core.bigint)("characters", {
|
|
746
|
+
mode: "number"
|
|
747
|
+
}),
|
|
748
|
+
requests: (0, import_mysql_core.int)("requests"),
|
|
749
|
+
/** The caller's own JSON, never read by the library. */
|
|
750
|
+
metadata: (0, import_mysql_core.json)("metadata").$type(),
|
|
751
|
+
/** `false` keeps the row out of the agent's quota windows (`recordUsage({ countsTowardsQuota: false })`). */
|
|
752
|
+
countsTowardsQuota: (0, import_mysql_core.boolean)("counts_towards_quota").notNull().default(true),
|
|
708
753
|
createdAt: ts("created_at").notNull()
|
|
709
754
|
}, (table) => [
|
|
710
755
|
(0, import_mysql_core.index)("agent_token_usage_actor_created_idx").on(table.actorRef, table.createdAt),
|
|
711
756
|
(0, import_mysql_core.index)("agent_token_usage_created_idx").on(table.createdAt),
|
|
712
|
-
(0, import_mysql_core.index)("agent_token_usage_thread_idx").on(table.threadId)
|
|
757
|
+
(0, import_mysql_core.index)("agent_token_usage_thread_idx").on(table.threadId),
|
|
758
|
+
(0, import_mysql_core.index)("agent_token_usage_feature_created_idx").on(table.feature, table.createdAt)
|
|
713
759
|
]);
|
|
714
760
|
var agentGenuiCall2 = (0, import_mysql_core.mysqlTable)("agent_genui_call", {
|
|
715
761
|
id: key("id").primaryKey(),
|
|
@@ -781,7 +827,15 @@ var agentRun2 = (0, import_mysql_core.mysqlTable)("agent_run", {
|
|
|
781
827
|
startedAt: ts("started_at").notNull(),
|
|
782
828
|
settledAt: ts("settled_at"),
|
|
783
829
|
promptHash: key("prompt_hash"),
|
|
784
|
-
parentRunId: key("parent_run_id")
|
|
830
|
+
parentRunId: key("parent_run_id"),
|
|
831
|
+
/** Enqueue → body start (ms); null when not read. */
|
|
832
|
+
queueMs: (0, import_mysql_core.int)("queue_ms"),
|
|
833
|
+
/** Where the completed run's time went: model and tool totals, counts, and the per-step list. */
|
|
834
|
+
modelMs: (0, import_mysql_core.int)("model_ms"),
|
|
835
|
+
toolsMs: (0, import_mysql_core.int)("tools_ms"),
|
|
836
|
+
modelCalls: (0, import_mysql_core.int)("model_calls"),
|
|
837
|
+
toolCalls: (0, import_mysql_core.int)("tool_calls"),
|
|
838
|
+
timings: (0, import_mysql_core.json)("timings").$type()
|
|
785
839
|
}, (table) => [
|
|
786
840
|
(0, import_mysql_core.index)("agent_run_started_idx").on(table.startedAt)
|
|
787
841
|
]);
|
|
@@ -1153,7 +1207,7 @@ var agentQueuedMessage3 = (0, import_pg_core.pgTable)("agent_queued_message", {
|
|
|
1153
1207
|
]);
|
|
1154
1208
|
var agentTokenUsage3 = (0, import_pg_core.pgTable)("agent_token_usage", {
|
|
1155
1209
|
id: (0, import_pg_core.text)("id").primaryKey(),
|
|
1156
|
-
threadId: (0, import_pg_core.text)("thread_id").
|
|
1210
|
+
threadId: (0, import_pg_core.text)("thread_id").references(() => agentThread3.id, {
|
|
1157
1211
|
onDelete: "cascade"
|
|
1158
1212
|
}),
|
|
1159
1213
|
actorRef: (0, import_pg_core.text)("actor_ref").notNull(),
|
|
@@ -1167,11 +1221,28 @@ var agentTokenUsage3 = (0, import_pg_core.pgTable)("agent_token_usage", {
|
|
|
1167
1221
|
costUsd: (0, import_pg_core.doublePrecision)("cost_usd"),
|
|
1168
1222
|
/** Where `cost_usd` came from: `'provider'` (reported) or `'estimate'` (tokens × the price row); null on rows from before it existed (reported). */
|
|
1169
1223
|
costSource: (0, import_pg_core.text)("cost_source").$type(),
|
|
1224
|
+
/** The run the row belongs to. */
|
|
1225
|
+
runId: (0, import_pg_core.text)("run_id"),
|
|
1226
|
+
/** What the spend was for: `agent:<name>` for an agent turn, the app's own otherwise; null → `agent`. */
|
|
1227
|
+
feature: (0, import_pg_core.text)("feature"),
|
|
1228
|
+
provider: (0, import_pg_core.text)("provider"),
|
|
1229
|
+
tenantRef: (0, import_pg_core.text)("tenant_ref"),
|
|
1230
|
+
/** Units a row bills by when they are not tokens. */
|
|
1231
|
+
audioSeconds: (0, import_pg_core.doublePrecision)("audio_seconds"),
|
|
1232
|
+
characters: (0, import_pg_core.bigint)("characters", {
|
|
1233
|
+
mode: "number"
|
|
1234
|
+
}),
|
|
1235
|
+
requests: (0, import_pg_core.integer)("requests"),
|
|
1236
|
+
/** The caller's own JSON, never read by the library. */
|
|
1237
|
+
metadata: (0, import_pg_core.jsonb)("metadata").$type(),
|
|
1238
|
+
/** `false` keeps the row out of the agent's quota windows (`recordUsage({ countsTowardsQuota: false })`). */
|
|
1239
|
+
countsTowardsQuota: (0, import_pg_core.boolean)("counts_towards_quota").notNull().default(true),
|
|
1170
1240
|
createdAt: ts2("created_at").notNull()
|
|
1171
1241
|
}, (table) => [
|
|
1172
1242
|
(0, import_pg_core.index)("agent_token_usage_actor_created_idx").on(table.actorRef, table.createdAt),
|
|
1173
1243
|
(0, import_pg_core.index)("agent_token_usage_created_idx").on(table.createdAt),
|
|
1174
|
-
(0, import_pg_core.index)("agent_token_usage_thread_idx").on(table.threadId)
|
|
1244
|
+
(0, import_pg_core.index)("agent_token_usage_thread_idx").on(table.threadId),
|
|
1245
|
+
(0, import_pg_core.index)("agent_token_usage_feature_created_idx").on(table.feature, table.createdAt)
|
|
1175
1246
|
]);
|
|
1176
1247
|
var agentGenuiCall3 = (0, import_pg_core.pgTable)("agent_genui_call", {
|
|
1177
1248
|
id: (0, import_pg_core.text)("id").primaryKey(),
|
|
@@ -1243,7 +1314,15 @@ var agentRun3 = (0, import_pg_core.pgTable)("agent_run", {
|
|
|
1243
1314
|
startedAt: ts2("started_at").notNull(),
|
|
1244
1315
|
settledAt: ts2("settled_at"),
|
|
1245
1316
|
promptHash: (0, import_pg_core.text)("prompt_hash"),
|
|
1246
|
-
parentRunId: (0, import_pg_core.text)("parent_run_id")
|
|
1317
|
+
parentRunId: (0, import_pg_core.text)("parent_run_id"),
|
|
1318
|
+
/** Enqueue → body start (ms); null when not read. */
|
|
1319
|
+
queueMs: (0, import_pg_core.integer)("queue_ms"),
|
|
1320
|
+
/** Where the completed run's time went: model and tool totals, counts, and the per-step list. */
|
|
1321
|
+
modelMs: (0, import_pg_core.integer)("model_ms"),
|
|
1322
|
+
toolsMs: (0, import_pg_core.integer)("tools_ms"),
|
|
1323
|
+
modelCalls: (0, import_pg_core.integer)("model_calls"),
|
|
1324
|
+
toolCalls: (0, import_pg_core.integer)("tool_calls"),
|
|
1325
|
+
timings: (0, import_pg_core.jsonb)("timings").$type()
|
|
1247
1326
|
}, (table) => [
|
|
1248
1327
|
(0, import_pg_core.index)("agent_run_started_idx").on(table.startedAt)
|
|
1249
1328
|
]);
|
|
@@ -1701,10 +1780,60 @@ function specs(dialect) {
|
|
|
1701
1780
|
}
|
|
1702
1781
|
__name(specs, "specs");
|
|
1703
1782
|
async function existingColumns(db, dialect, table) {
|
|
1704
|
-
|
|
1705
|
-
return new Set(rows.map((row) => String(row.name)));
|
|
1783
|
+
return new Set((await columnNullability(db, dialect, table)).keys());
|
|
1706
1784
|
}
|
|
1707
1785
|
__name(existingColumns, "existingColumns");
|
|
1786
|
+
async function columnNullability(db, dialect, table) {
|
|
1787
|
+
if (dialect === "sqlite") {
|
|
1788
|
+
const rows2 = await querySql(db, dialect, import_drizzle_orm2.sql.raw(`PRAGMA table_info("${table}")`));
|
|
1789
|
+
return new Map(rows2.map((row) => [
|
|
1790
|
+
String(row.name),
|
|
1791
|
+
Number(row.notnull) === 0
|
|
1792
|
+
]));
|
|
1793
|
+
}
|
|
1794
|
+
const rows = await querySql(db, dialect, import_drizzle_orm2.sql`select column_name as name, is_nullable as nullable from information_schema.columns where table_schema = ${import_drizzle_orm2.sql.raw(dialect === "mysql" ? "database()" : "current_schema()")} and table_name = ${table}`);
|
|
1795
|
+
return new Map(rows.map((row) => [
|
|
1796
|
+
String(row.name ?? row.NAME),
|
|
1797
|
+
String(row.nullable ?? row.NULLABLE).toUpperCase() === "YES"
|
|
1798
|
+
]));
|
|
1799
|
+
}
|
|
1800
|
+
__name(columnNullability, "columnNullability");
|
|
1801
|
+
async function relaxNotNull(db, dialect, spec, column, all) {
|
|
1802
|
+
const q = /* @__PURE__ */ __name((identifier) => quote(dialect, identifier), "q");
|
|
1803
|
+
if (dialect === "postgres") {
|
|
1804
|
+
await runSql(db, dialect, import_drizzle_orm2.sql.raw(`ALTER TABLE ${q(spec.name)} ALTER COLUMN ${q(column.name)} DROP NOT NULL`));
|
|
1805
|
+
return;
|
|
1806
|
+
}
|
|
1807
|
+
if (dialect === "mysql") {
|
|
1808
|
+
await runSql(db, dialect, import_drizzle_orm2.sql.raw(`ALTER TABLE ${q(spec.name)} MODIFY ${columnDefinition(dialect, column)}`));
|
|
1809
|
+
return;
|
|
1810
|
+
}
|
|
1811
|
+
if (all.some((other) => other.foreignKeys.some((key2) => key2.table === spec.name && other !== spec))) {
|
|
1812
|
+
throw new Error(`agent schema: cannot make ${spec.name}.${column.name} nullable on SQLite \u2014 other tables reference ${spec.name}`);
|
|
1813
|
+
}
|
|
1814
|
+
const scratch = `${spec.name}__rebuild`;
|
|
1815
|
+
const present = [
|
|
1816
|
+
...(await columnNullability(db, dialect, spec.name)).keys()
|
|
1817
|
+
];
|
|
1818
|
+
const list = present.map(q).join(", ");
|
|
1819
|
+
await runSql(db, dialect, import_drizzle_orm2.sql.raw("SAVEPOINT agent_schema_rebuild"));
|
|
1820
|
+
try {
|
|
1821
|
+
await runSql(db, dialect, import_drizzle_orm2.sql.raw(`DROP TABLE IF EXISTS ${q(scratch)}`));
|
|
1822
|
+
await runSql(db, dialect, import_drizzle_orm2.sql.raw(createTableSql(dialect, {
|
|
1823
|
+
...spec,
|
|
1824
|
+
name: scratch
|
|
1825
|
+
})));
|
|
1826
|
+
await runSql(db, dialect, import_drizzle_orm2.sql.raw(`INSERT INTO ${q(scratch)} (${list}) SELECT ${list} FROM ${q(spec.name)}`));
|
|
1827
|
+
await runSql(db, dialect, import_drizzle_orm2.sql.raw(`DROP TABLE ${q(spec.name)}`));
|
|
1828
|
+
await runSql(db, dialect, import_drizzle_orm2.sql.raw(`ALTER TABLE ${q(scratch)} RENAME TO ${q(spec.name)}`));
|
|
1829
|
+
await runSql(db, dialect, import_drizzle_orm2.sql.raw("RELEASE SAVEPOINT agent_schema_rebuild"));
|
|
1830
|
+
} catch (error) {
|
|
1831
|
+
await runSql(db, dialect, import_drizzle_orm2.sql.raw("ROLLBACK TO SAVEPOINT agent_schema_rebuild")).catch(() => void 0);
|
|
1832
|
+
await runSql(db, dialect, import_drizzle_orm2.sql.raw("RELEASE SAVEPOINT agent_schema_rebuild")).catch(() => void 0);
|
|
1833
|
+
throw error;
|
|
1834
|
+
}
|
|
1835
|
+
}
|
|
1836
|
+
__name(relaxNotNull, "relaxNotNull");
|
|
1708
1837
|
async function indexExists(db, dialect, table, index4) {
|
|
1709
1838
|
let query;
|
|
1710
1839
|
if (dialect === "sqlite") {
|
|
@@ -1718,7 +1847,8 @@ async function indexExists(db, dialect, table, index4) {
|
|
|
1718
1847
|
}
|
|
1719
1848
|
__name(indexExists, "indexExists");
|
|
1720
1849
|
async function heal(db, dialect) {
|
|
1721
|
-
|
|
1850
|
+
const all = specs(dialect);
|
|
1851
|
+
for (const spec of all) {
|
|
1722
1852
|
await runSql(db, dialect, import_drizzle_orm2.sql.raw(createTableSql(dialect, spec)));
|
|
1723
1853
|
const present = await existingColumns(db, dialect, spec.name);
|
|
1724
1854
|
for (const column of spec.columns) {
|
|
@@ -1726,6 +1856,13 @@ async function heal(db, dialect) {
|
|
|
1726
1856
|
await runSql(db, dialect, import_drizzle_orm2.sql.raw(`ALTER TABLE ${quote(dialect, spec.name)} ADD COLUMN ${columnDefinition(dialect, column)}`));
|
|
1727
1857
|
}
|
|
1728
1858
|
}
|
|
1859
|
+
const nullable3 = await columnNullability(db, dialect, spec.name);
|
|
1860
|
+
for (const column of spec.columns) {
|
|
1861
|
+
if (column.notNull || spec.primaryKey.includes(column.name)) continue;
|
|
1862
|
+
if (nullable3.get(column.name) === false) {
|
|
1863
|
+
await relaxNotNull(db, dialect, spec, column, all);
|
|
1864
|
+
}
|
|
1865
|
+
}
|
|
1729
1866
|
for (const index4 of spec.indexes) {
|
|
1730
1867
|
if (!await indexExists(db, dialect, spec.name, index4.name)) {
|
|
1731
1868
|
await runSql(db, dialect, import_drizzle_orm2.sql.raw(createIndexSql(dialect, spec.name, index4)));
|
|
@@ -2916,7 +3053,13 @@ var DrizzleAgentStore = class {
|
|
|
2916
3053
|
startedAt: /* @__PURE__ */ new Date(),
|
|
2917
3054
|
settledAt: null,
|
|
2918
3055
|
promptHash: run.promptHash ?? null,
|
|
2919
|
-
parentRunId: run.parentRunId ?? null
|
|
3056
|
+
parentRunId: run.parentRunId ?? null,
|
|
3057
|
+
queueMs: run.queueMs !== void 0 ? Math.max(0, Math.round(run.queueMs)) : null,
|
|
3058
|
+
modelMs: null,
|
|
3059
|
+
toolsMs: null,
|
|
3060
|
+
modelCalls: null,
|
|
3061
|
+
toolCalls: null,
|
|
3062
|
+
timings: null
|
|
2920
3063
|
};
|
|
2921
3064
|
await this.db.insert(this.t.agentRun).values(runRow);
|
|
2922
3065
|
}
|
|
@@ -2944,6 +3087,13 @@ var DrizzleAgentStore = class {
|
|
|
2944
3087
|
if (end.errorMessage !== void 0) {
|
|
2945
3088
|
updates.errorMessage = end.errorMessage;
|
|
2946
3089
|
}
|
|
3090
|
+
if (end.timings !== void 0) {
|
|
3091
|
+
updates.modelMs = Math.round(end.timings.modelMs);
|
|
3092
|
+
updates.toolsMs = Math.round(end.timings.toolsMs);
|
|
3093
|
+
updates.modelCalls = end.timings.modelCalls;
|
|
3094
|
+
updates.toolCalls = end.timings.toolCalls;
|
|
3095
|
+
updates.timings = end.timings.steps;
|
|
3096
|
+
}
|
|
2947
3097
|
await this.db.update(this.t.agentRun).set(updates).where((0, import_drizzle_orm4.eq)(this.t.agentRun.id, end.runId));
|
|
2948
3098
|
}
|
|
2949
3099
|
/** Bump the run's llm-step retry counter. Atomic `retries = retries + 1`, no read-modify-write. */
|
|
@@ -3146,9 +3296,18 @@ var DrizzleAgentStore = class {
|
|
|
3146
3296
|
async recordUsage(input) {
|
|
3147
3297
|
await this.db.insert(this.t.agentTokenUsage).values({
|
|
3148
3298
|
id: crypto.randomUUID(),
|
|
3149
|
-
threadId: input.threadId,
|
|
3299
|
+
threadId: input.threadId ?? null,
|
|
3150
3300
|
actorRef: input.actorRef,
|
|
3151
3301
|
messageId: input.messageId ?? null,
|
|
3302
|
+
runId: input.runId ?? null,
|
|
3303
|
+
feature: input.feature ?? null,
|
|
3304
|
+
provider: input.provider ?? null,
|
|
3305
|
+
tenantRef: input.tenantRef ?? null,
|
|
3306
|
+
audioSeconds: input.audioSeconds ?? null,
|
|
3307
|
+
characters: input.characters ?? null,
|
|
3308
|
+
requests: input.requests ?? null,
|
|
3309
|
+
metadata: input.metadata ?? null,
|
|
3310
|
+
countsTowardsQuota: input.countsTowardsQuota !== false,
|
|
3152
3311
|
modelId: input.modelId,
|
|
3153
3312
|
purpose: input.purpose,
|
|
3154
3313
|
inputTokens: input.usage.inputTokens,
|
|
@@ -3233,7 +3392,7 @@ var DrizzleAgentStore = class {
|
|
|
3233
3392
|
});
|
|
3234
3393
|
const from = new Date(Math.min(...bounds.map(({ start }) => start.getTime())));
|
|
3235
3394
|
const to = new Date(Math.max(...bounds.map(({ end }) => end.getTime())));
|
|
3236
|
-
const [row] = await this.db.select(columns).from(usage).where((0, import_drizzle_orm4.and)((0, import_drizzle_orm4.eq)(usage.actorRef, actorRef), within(from, to)));
|
|
3395
|
+
const [row] = await this.db.select(columns).from(usage).where((0, import_drizzle_orm4.and)((0, import_drizzle_orm4.eq)(usage.actorRef, actorRef), within(from, to), (0, import_drizzle_orm4.eq)(usage.countsTowardsQuota, true)));
|
|
3237
3396
|
return bounds.map((_, index4) => ({
|
|
3238
3397
|
usedTokens: Number(row?.[`tokens${index4}`] ?? 0),
|
|
3239
3398
|
costUsd: Number(row?.[`cost${index4}`] ?? 0),
|
|
@@ -3466,10 +3625,26 @@ function toRecentRunRow(run) {
|
|
|
3466
3625
|
retries: run.retries,
|
|
3467
3626
|
startedAt: run.startedAt.toISOString(),
|
|
3468
3627
|
promptHash: run.promptHash ?? null,
|
|
3469
|
-
parentRunId: run.parentRunId ?? null
|
|
3628
|
+
parentRunId: run.parentRunId ?? null,
|
|
3629
|
+
queueMs: run.queueMs ?? null,
|
|
3630
|
+
modelMs: run.modelMs ?? null,
|
|
3631
|
+
toolsMs: run.toolsMs ?? null,
|
|
3632
|
+
modelCalls: run.modelCalls ?? null,
|
|
3633
|
+
toolCalls: run.toolCalls ?? null
|
|
3470
3634
|
};
|
|
3471
3635
|
}
|
|
3472
3636
|
__name(toRecentRunRow, "toRecentRunRow");
|
|
3637
|
+
function toRunTimings(run) {
|
|
3638
|
+
if (!Array.isArray(run.timings)) return null;
|
|
3639
|
+
return {
|
|
3640
|
+
modelMs: run.modelMs ?? 0,
|
|
3641
|
+
toolsMs: run.toolsMs ?? 0,
|
|
3642
|
+
modelCalls: run.modelCalls ?? 0,
|
|
3643
|
+
toolCalls: run.toolCalls ?? 0,
|
|
3644
|
+
steps: run.timings
|
|
3645
|
+
};
|
|
3646
|
+
}
|
|
3647
|
+
__name(toRunTimings, "toRunTimings");
|
|
3473
3648
|
function toRunToolCallRow(toolCall) {
|
|
3474
3649
|
return {
|
|
3475
3650
|
toolCallId: toolCall.id,
|
|
@@ -3485,6 +3660,12 @@ function toRunToolCallRow(toolCall) {
|
|
|
3485
3660
|
__name(toRunToolCallRow, "toRunToolCallRow");
|
|
3486
3661
|
function toUsageInput(row) {
|
|
3487
3662
|
return {
|
|
3663
|
+
feature: row.feature ?? null,
|
|
3664
|
+
purpose: row.purpose ?? null,
|
|
3665
|
+
costSource: row.costSource ?? null,
|
|
3666
|
+
audioSeconds: row.audioSeconds == null ? null : Number(row.audioSeconds),
|
|
3667
|
+
characters: row.characters == null ? null : Number(row.characters),
|
|
3668
|
+
requests: row.requests ?? null,
|
|
3488
3669
|
modelId: row.modelId,
|
|
3489
3670
|
actorRef: row.actorRef,
|
|
3490
3671
|
threadId: row.threadId,
|
|
@@ -3532,8 +3713,13 @@ var DrizzleGovernanceQueries = class {
|
|
|
3532
3713
|
}
|
|
3533
3714
|
return pricing;
|
|
3534
3715
|
}
|
|
3535
|
-
|
|
3536
|
-
|
|
3716
|
+
/**
|
|
3717
|
+
* The usage rows in range, with only what the bucketers read: `requests` always (a recorded row
|
|
3718
|
+
* counts as its own requests in every rollup), and the feature/unit columns only for the
|
|
3719
|
+
* per-feature reads that group by them.
|
|
3720
|
+
*/
|
|
3721
|
+
async usageInRange(range, withFeature = false) {
|
|
3722
|
+
const { start, end } = (0, import_nestjs_agent_core5.usageRangeBounds)(range);
|
|
3537
3723
|
const usage = this.t.agentTokenUsage;
|
|
3538
3724
|
const rows = await this.db.select({
|
|
3539
3725
|
modelId: usage.modelId,
|
|
@@ -3544,14 +3730,30 @@ var DrizzleGovernanceQueries = class {
|
|
|
3544
3730
|
outputTokens: usage.outputTokens,
|
|
3545
3731
|
cacheWriteTokens: usage.cacheWriteTokens,
|
|
3546
3732
|
cacheReadTokens: usage.cacheReadTokens,
|
|
3547
|
-
costUsd: usage.costUsd
|
|
3548
|
-
|
|
3733
|
+
costUsd: usage.costUsd,
|
|
3734
|
+
requests: usage.requests,
|
|
3735
|
+
...withFeature ? {
|
|
3736
|
+
feature: usage.feature,
|
|
3737
|
+
purpose: usage.purpose,
|
|
3738
|
+
costSource: usage.costSource,
|
|
3739
|
+
audioSeconds: usage.audioSeconds,
|
|
3740
|
+
characters: usage.characters
|
|
3741
|
+
} : {}
|
|
3742
|
+
}).from(usage).where((0, import_drizzle_orm5.and)((0, import_drizzle_orm5.gte)(this.t.agentTokenUsage.createdAt, start), (0, import_drizzle_orm5.lt)(this.t.agentTokenUsage.createdAt, end)));
|
|
3549
3743
|
return rows.map(toUsageInput);
|
|
3550
3744
|
}
|
|
3551
3745
|
async spendByModel(range) {
|
|
3552
3746
|
const pricing = await this.loadPricing();
|
|
3553
3747
|
return (0, import_nestjs_agent_core5.bucketByModel)(await this.usageInRange(range), pricing);
|
|
3554
3748
|
}
|
|
3749
|
+
async spendByFeature(range) {
|
|
3750
|
+
const pricing = await this.loadPricing();
|
|
3751
|
+
return (0, import_nestjs_agent_core5.bucketByFeature)(await this.usageInRange(range, true), pricing);
|
|
3752
|
+
}
|
|
3753
|
+
async usageBreakdown(range, filter) {
|
|
3754
|
+
const pricing = await this.loadPricing();
|
|
3755
|
+
return (0, import_nestjs_agent_core5.bucketUsageBreakdown)(await this.usageInRange(range, true), pricing, filter);
|
|
3756
|
+
}
|
|
3555
3757
|
async spendByActor(range) {
|
|
3556
3758
|
const pricing = await this.loadPricing();
|
|
3557
3759
|
return (0, import_nestjs_agent_core5.bucketByActor)(await this.usageInRange(range), pricing);
|
|
@@ -3565,7 +3767,9 @@ var DrizzleGovernanceQueries = class {
|
|
|
3565
3767
|
const pricing = await this.loadPricing();
|
|
3566
3768
|
const rows = await this.usageInRange(range);
|
|
3567
3769
|
const threadIds = [
|
|
3568
|
-
...new Set(rows.
|
|
3770
|
+
...new Set(rows.flatMap((row) => row.threadId === null ? [] : [
|
|
3771
|
+
row.threadId
|
|
3772
|
+
]))
|
|
3569
3773
|
];
|
|
3570
3774
|
if (threadIds.length === 0) {
|
|
3571
3775
|
return [];
|
|
@@ -3643,6 +3847,7 @@ var DrizzleGovernanceQueries = class {
|
|
|
3643
3847
|
outputTokens: (0, import_drizzle_orm5.sum)(this.t.agentTokenUsage.outputTokens)
|
|
3644
3848
|
}).from(this.t.agentTokenUsage).where((0, import_drizzle_orm5.inArray)(this.t.agentTokenUsage.threadId, threadIds)).groupBy(this.t.agentTokenUsage.threadId);
|
|
3645
3849
|
for (const row of usageTotals) {
|
|
3850
|
+
if (row.threadId === null) continue;
|
|
3646
3851
|
const bucket = rollups.get(row.threadId);
|
|
3647
3852
|
if (bucket !== void 0) {
|
|
3648
3853
|
bucket.totalTokens = Number(row.inputTokens ?? 0) + Number(row.outputTokens ?? 0);
|
|
@@ -4019,7 +4224,8 @@ var DrizzleGovernanceQueries = class {
|
|
|
4019
4224
|
actorRef: row.thread.actorRef,
|
|
4020
4225
|
deleted: row.thread.deletedAt != null
|
|
4021
4226
|
},
|
|
4022
|
-
toolCalls: toolCalls.map(toRunToolCallRow)
|
|
4227
|
+
toolCalls: toolCalls.map(toRunToolCallRow),
|
|
4228
|
+
timings: toRunTimings(row.run)
|
|
4023
4229
|
};
|
|
4024
4230
|
}
|
|
4025
4231
|
/**
|