@dudousxd/nestjs-agent-store-drizzle 0.8.2 → 0.10.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/README.md +126 -3
- package/dist/index.cjs +808 -32
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1965 -534
- package/dist/index.d.ts +1965 -534
- package/dist/index.js +792 -21
- package/dist/index.js.map +1 -1
- package/package.json +6 -4
package/dist/index.cjs
CHANGED
|
@@ -8,11 +8,11 @@ var __export = (target, all) => {
|
|
|
8
8
|
for (var name in all)
|
|
9
9
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
10
|
};
|
|
11
|
-
var __copyProps = (to, from, except,
|
|
11
|
+
var __copyProps = (to, from, except, desc4) => {
|
|
12
12
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
13
|
for (let key of __getOwnPropNames(from))
|
|
14
14
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc4 = __getOwnPropDesc(from, key)) || desc4.enumerable });
|
|
16
16
|
}
|
|
17
17
|
return to;
|
|
18
18
|
};
|
|
@@ -24,7 +24,11 @@ __export(index_exports, {
|
|
|
24
24
|
DrizzleAgentStore: () => DrizzleAgentStore,
|
|
25
25
|
DrizzleAgentStoreModule: () => DrizzleAgentStoreModule,
|
|
26
26
|
DrizzleGovernanceQueries: () => DrizzleGovernanceQueries,
|
|
27
|
+
DrizzleMemoryProvider: () => DrizzleMemoryProvider,
|
|
27
28
|
DrizzlePricingStore: () => DrizzlePricingStore,
|
|
29
|
+
DrizzleRagIngestionLog: () => DrizzleRagIngestionLog,
|
|
30
|
+
RAG_INGESTION_LOG_PAGE_ORDER: () => RAG_INGESTION_LOG_PAGE_ORDER,
|
|
31
|
+
agentMemory: () => agentMemory,
|
|
28
32
|
agentMessage: () => agentMessage,
|
|
29
33
|
agentModelPricing: () => agentModelPricing,
|
|
30
34
|
agentRun: () => agentRun,
|
|
@@ -32,7 +36,8 @@ __export(index_exports, {
|
|
|
32
36
|
agentThread: () => agentThread,
|
|
33
37
|
agentTokenUsage: () => agentTokenUsage,
|
|
34
38
|
agentToolCall: () => agentToolCall,
|
|
35
|
-
ensureAgentSchema: () => ensureAgentSchema
|
|
39
|
+
ensureAgentSchema: () => ensureAgentSchema,
|
|
40
|
+
ragIngestionLog: () => ragIngestionLog
|
|
36
41
|
});
|
|
37
42
|
module.exports = __toCommonJS(index_exports);
|
|
38
43
|
|
|
@@ -47,6 +52,8 @@ var agentThread = (0, import_sqlite_core.sqliteTable)("agent_thread", {
|
|
|
47
52
|
mode: "boolean"
|
|
48
53
|
}).notNull().default(false),
|
|
49
54
|
activeStreamId: (0, import_sqlite_core.text)("active_stream_id"),
|
|
55
|
+
/** The agent a new turn on this thread defaults to when the caller names none. */
|
|
56
|
+
defaultAgent: (0, import_sqlite_core.text)("default_agent"),
|
|
50
57
|
createdAt: (0, import_sqlite_core.integer)("created_at", {
|
|
51
58
|
mode: "timestamp_ms"
|
|
52
59
|
}).notNull(),
|
|
@@ -72,6 +79,9 @@ var agentMessage = (0, import_sqlite_core.sqliteTable)("agent_message", {
|
|
|
72
79
|
toolResults: (0, import_sqlite_core.text)("tool_results", {
|
|
73
80
|
mode: "json"
|
|
74
81
|
}).$type(),
|
|
82
|
+
attachments: (0, import_sqlite_core.text)("attachments", {
|
|
83
|
+
mode: "json"
|
|
84
|
+
}).$type(),
|
|
75
85
|
followUps: (0, import_sqlite_core.text)("follow_ups", {
|
|
76
86
|
mode: "json"
|
|
77
87
|
}).$type(),
|
|
@@ -79,6 +89,7 @@ var agentMessage = (0, import_sqlite_core.sqliteTable)("agent_message", {
|
|
|
79
89
|
mode: "json"
|
|
80
90
|
}).$type(),
|
|
81
91
|
agentName: (0, import_sqlite_core.text)("agent_name"),
|
|
92
|
+
runId: (0, import_sqlite_core.text)("run_id"),
|
|
82
93
|
createdAt: (0, import_sqlite_core.integer)("created_at", {
|
|
83
94
|
mode: "timestamp_ms"
|
|
84
95
|
}).notNull()
|
|
@@ -110,7 +121,9 @@ var agentToolCall = (0, import_sqlite_core.sqliteTable)("agent_tool_call", {
|
|
|
110
121
|
}),
|
|
111
122
|
/** The run (turn) this call belongs to, for a trace deep-link; null for a pre-rollout row. */
|
|
112
123
|
runId: (0, import_sqlite_core.text)("run_id")
|
|
113
|
-
})
|
|
124
|
+
}, (table) => [
|
|
125
|
+
(0, import_sqlite_core.index)("agent_tool_call_message_idx").on(table.messageId)
|
|
126
|
+
]);
|
|
114
127
|
var agentTokenUsage = (0, import_sqlite_core.sqliteTable)("agent_token_usage", {
|
|
115
128
|
id: (0, import_sqlite_core.text)("id").primaryKey(),
|
|
116
129
|
threadId: (0, import_sqlite_core.text)("thread_id").notNull().references(() => agentThread.id, {
|
|
@@ -169,17 +182,79 @@ var agentRun = (0, import_sqlite_core.sqliteTable)("agent_run", {
|
|
|
169
182
|
mode: "timestamp_ms"
|
|
170
183
|
}),
|
|
171
184
|
/** sha256 hex of the run's resolved (pre-RAG) system prompt; null for a pre-existing run. */
|
|
172
|
-
promptHash: (0, import_sqlite_core.text)("prompt_hash")
|
|
185
|
+
promptHash: (0, import_sqlite_core.text)("prompt_hash"),
|
|
186
|
+
/**
|
|
187
|
+
* The run that delegated this one; null for a turn nobody delegated. The durable runtime's
|
|
188
|
+
* journal holds the same edge, but only there — this column is what lets a reader of run ROWS
|
|
189
|
+
* build the delegation tree and roll a child's cost up to the turn that asked for it, including
|
|
190
|
+
* for a detached child, which outlives its parent's turn and so is paired by nothing in the
|
|
191
|
+
* transcript.
|
|
192
|
+
*/
|
|
193
|
+
parentRunId: (0, import_sqlite_core.text)("parent_run_id")
|
|
173
194
|
}, (table) => [
|
|
174
195
|
(0, import_sqlite_core.index)("agent_run_started_idx").on(table.startedAt)
|
|
175
196
|
]);
|
|
197
|
+
var agentMemory = (0, import_sqlite_core.sqliteTable)("agent_memory", {
|
|
198
|
+
id: (0, import_sqlite_core.text)("id").primaryKey(),
|
|
199
|
+
/** The opaque scope token. Unique with `key`: one fact per key per scope. */
|
|
200
|
+
scope: (0, import_sqlite_core.text)("scope").notNull(),
|
|
201
|
+
/** What the fact is ABOUT. Two scopes sharing a key are one question answered twice. */
|
|
202
|
+
key: (0, import_sqlite_core.text)("key").notNull(),
|
|
203
|
+
/** The fact itself, one line, as the model reads it. */
|
|
204
|
+
text: (0, import_sqlite_core.text)("text").notNull(),
|
|
205
|
+
originAuthor: (0, import_sqlite_core.text)("origin_author").$type().notNull(),
|
|
206
|
+
/** A pointer that is allowed to dangle — see the table note. */
|
|
207
|
+
originThreadId: (0, import_sqlite_core.text)("origin_thread_id"),
|
|
208
|
+
originRunId: (0, import_sqlite_core.text)("origin_run_id"),
|
|
209
|
+
originActorRef: (0, import_sqlite_core.text)("origin_actor_ref"),
|
|
210
|
+
/** Always-on: carried in every prompt. Set by a host's console, never by a write. */
|
|
211
|
+
pinned: (0, import_sqlite_core.integer)("pinned", {
|
|
212
|
+
mode: "boolean"
|
|
213
|
+
}).notNull().default(false),
|
|
214
|
+
createdAt: (0, import_sqlite_core.integer)("created_at", {
|
|
215
|
+
mode: "timestamp_ms"
|
|
216
|
+
}).notNull(),
|
|
217
|
+
updatedAt: (0, import_sqlite_core.integer)("updated_at", {
|
|
218
|
+
mode: "timestamp_ms"
|
|
219
|
+
}).notNull()
|
|
220
|
+
}, (table) => [
|
|
221
|
+
(0, import_sqlite_core.uniqueIndex)("agent_memory_scope_key_uq").on(table.scope, table.key)
|
|
222
|
+
]);
|
|
223
|
+
var ragIngestionLog = (0, import_sqlite_core.sqliteTable)("rag_ingestion_log", {
|
|
224
|
+
/** The vector-store document id (chunk ids are `${documentId}#<n>`). */
|
|
225
|
+
documentId: (0, import_sqlite_core.text)("document_id").primaryKey(),
|
|
226
|
+
status: (0, import_sqlite_core.text)("status").$type().notNull(),
|
|
227
|
+
collection: (0, import_sqlite_core.text)("collection"),
|
|
228
|
+
ownerType: (0, import_sqlite_core.text)("owner_type"),
|
|
229
|
+
ownerId: (0, import_sqlite_core.text)("owner_id"),
|
|
230
|
+
/** Citation-facing origin — the media record's path. */
|
|
231
|
+
source: (0, import_sqlite_core.text)("source"),
|
|
232
|
+
mimeType: (0, import_sqlite_core.text)("mime_type"),
|
|
233
|
+
size: (0, import_sqlite_core.integer)("size"),
|
|
234
|
+
/** Chunk count on `ingested`; null otherwise. */
|
|
235
|
+
chunks: (0, import_sqlite_core.integer)("chunks"),
|
|
236
|
+
/** Skip reason on `skipped` (`unsupported-type` | `too-large` | `empty-text`); null otherwise. */
|
|
237
|
+
reason: (0, import_sqlite_core.text)("reason"),
|
|
238
|
+
/** Error message on `failed`; null otherwise. */
|
|
239
|
+
error: (0, import_sqlite_core.text)("error"),
|
|
240
|
+
createdAt: (0, import_sqlite_core.integer)("created_at", {
|
|
241
|
+
mode: "timestamp_ms"
|
|
242
|
+
}).notNull(),
|
|
243
|
+
updatedAt: (0, import_sqlite_core.integer)("updated_at", {
|
|
244
|
+
mode: "timestamp_ms"
|
|
245
|
+
}).notNull()
|
|
246
|
+
}, (table) => [
|
|
247
|
+
(0, import_sqlite_core.index)("rag_ingestion_log_collection_idx").on(table.collection, table.updatedAt)
|
|
248
|
+
]);
|
|
176
249
|
var agentSchema = {
|
|
177
250
|
agentThread,
|
|
178
251
|
agentMessage,
|
|
179
252
|
agentToolCall,
|
|
180
253
|
agentTokenUsage,
|
|
181
254
|
agentModelPricing,
|
|
182
|
-
agentRun
|
|
255
|
+
agentRun,
|
|
256
|
+
agentMemory,
|
|
257
|
+
ragIngestionLog
|
|
183
258
|
};
|
|
184
259
|
|
|
185
260
|
// src/ensure-schema.ts
|
|
@@ -192,6 +267,7 @@ var statements = [
|
|
|
192
267
|
title TEXT NOT NULL,
|
|
193
268
|
transient INTEGER NOT NULL DEFAULT 0,
|
|
194
269
|
active_stream_id TEXT,
|
|
270
|
+
default_agent TEXT,
|
|
195
271
|
created_at INTEGER NOT NULL,
|
|
196
272
|
updated_at INTEGER NOT NULL,
|
|
197
273
|
deleted_at INTEGER
|
|
@@ -205,9 +281,11 @@ var statements = [
|
|
|
205
281
|
content TEXT NOT NULL,
|
|
206
282
|
tool_calls TEXT,
|
|
207
283
|
tool_results TEXT,
|
|
284
|
+
attachments TEXT,
|
|
208
285
|
follow_ups TEXT,
|
|
209
286
|
usage TEXT,
|
|
210
287
|
agent_name TEXT,
|
|
288
|
+
run_id TEXT,
|
|
211
289
|
created_at INTEGER NOT NULL
|
|
212
290
|
)`,
|
|
213
291
|
`CREATE INDEX IF NOT EXISTS agent_message_thread_created_idx
|
|
@@ -227,6 +305,8 @@ var statements = [
|
|
|
227
305
|
executed_at INTEGER,
|
|
228
306
|
run_id TEXT
|
|
229
307
|
)`,
|
|
308
|
+
`CREATE INDEX IF NOT EXISTS agent_tool_call_message_idx
|
|
309
|
+
ON agent_tool_call (message_id)`,
|
|
230
310
|
`CREATE TABLE IF NOT EXISTS agent_token_usage (
|
|
231
311
|
id TEXT PRIMARY KEY NOT NULL,
|
|
232
312
|
thread_id TEXT NOT NULL REFERENCES agent_thread(id) ON DELETE CASCADE,
|
|
@@ -265,20 +345,93 @@ var statements = [
|
|
|
265
345
|
retries INTEGER NOT NULL DEFAULT 0,
|
|
266
346
|
started_at INTEGER NOT NULL,
|
|
267
347
|
settled_at INTEGER,
|
|
268
|
-
prompt_hash TEXT
|
|
348
|
+
prompt_hash TEXT,
|
|
349
|
+
parent_run_id TEXT
|
|
269
350
|
)`,
|
|
270
351
|
`CREATE INDEX IF NOT EXISTS agent_run_started_idx
|
|
271
|
-
ON agent_run (started_at)
|
|
352
|
+
ON agent_run (started_at)`,
|
|
353
|
+
// `key` and `text` are quoted: both are keywords in at least one engine this DDL is read by, and
|
|
354
|
+
// they are the SPI's own field names, which is worth more here than dodging the quoting.
|
|
355
|
+
`CREATE TABLE IF NOT EXISTS agent_memory (
|
|
356
|
+
id TEXT PRIMARY KEY NOT NULL,
|
|
357
|
+
scope TEXT NOT NULL,
|
|
358
|
+
"key" TEXT NOT NULL,
|
|
359
|
+
"text" TEXT NOT NULL,
|
|
360
|
+
origin_author TEXT NOT NULL,
|
|
361
|
+
origin_thread_id TEXT,
|
|
362
|
+
origin_run_id TEXT,
|
|
363
|
+
origin_actor_ref TEXT,
|
|
364
|
+
pinned INTEGER NOT NULL DEFAULT 0,
|
|
365
|
+
created_at INTEGER NOT NULL,
|
|
366
|
+
updated_at INTEGER NOT NULL
|
|
367
|
+
)`,
|
|
368
|
+
`CREATE UNIQUE INDEX IF NOT EXISTS agent_memory_scope_key_uq
|
|
369
|
+
ON agent_memory (scope, "key")`,
|
|
370
|
+
`CREATE TABLE IF NOT EXISTS rag_ingestion_log (
|
|
371
|
+
document_id TEXT PRIMARY KEY NOT NULL,
|
|
372
|
+
status TEXT NOT NULL,
|
|
373
|
+
collection TEXT,
|
|
374
|
+
owner_type TEXT,
|
|
375
|
+
owner_id TEXT,
|
|
376
|
+
source TEXT,
|
|
377
|
+
mime_type TEXT,
|
|
378
|
+
size INTEGER,
|
|
379
|
+
chunks INTEGER,
|
|
380
|
+
reason TEXT,
|
|
381
|
+
error TEXT,
|
|
382
|
+
created_at INTEGER NOT NULL,
|
|
383
|
+
updated_at INTEGER NOT NULL
|
|
384
|
+
)`,
|
|
385
|
+
`CREATE INDEX IF NOT EXISTS rag_ingestion_log_collection_idx
|
|
386
|
+
ON rag_ingestion_log (collection, updated_at)`
|
|
387
|
+
];
|
|
388
|
+
var additiveColumns = [
|
|
389
|
+
{
|
|
390
|
+
table: "agent_message",
|
|
391
|
+
column: "run_id",
|
|
392
|
+
ddl: "ALTER TABLE agent_message ADD COLUMN run_id TEXT"
|
|
393
|
+
},
|
|
394
|
+
{
|
|
395
|
+
table: "agent_message",
|
|
396
|
+
column: "attachments",
|
|
397
|
+
ddl: "ALTER TABLE agent_message ADD COLUMN attachments TEXT"
|
|
398
|
+
},
|
|
399
|
+
{
|
|
400
|
+
table: "agent_thread",
|
|
401
|
+
column: "default_agent",
|
|
402
|
+
ddl: "ALTER TABLE agent_thread ADD COLUMN default_agent TEXT"
|
|
403
|
+
},
|
|
404
|
+
{
|
|
405
|
+
table: "agent_run",
|
|
406
|
+
column: "parent_run_id",
|
|
407
|
+
ddl: "ALTER TABLE agent_run ADD COLUMN parent_run_id TEXT"
|
|
408
|
+
}
|
|
272
409
|
];
|
|
273
410
|
async function ensureAgentSchema(db) {
|
|
274
411
|
for (const statement of statements) {
|
|
275
412
|
await db.run(import_drizzle_orm.sql.raw(statement));
|
|
276
413
|
}
|
|
414
|
+
for (const { table, column, ddl } of additiveColumns) {
|
|
415
|
+
const existing = await db.all(import_drizzle_orm.sql.raw(`PRAGMA table_info(${table})`));
|
|
416
|
+
if (!existing.some((row) => row.name === column)) {
|
|
417
|
+
await db.run(import_drizzle_orm.sql.raw(ddl));
|
|
418
|
+
}
|
|
419
|
+
}
|
|
277
420
|
}
|
|
278
421
|
__name(ensureAgentSchema, "ensureAgentSchema");
|
|
279
422
|
|
|
280
423
|
// src/drizzle-agent-store.ts
|
|
281
424
|
var import_drizzle_orm2 = require("drizzle-orm");
|
|
425
|
+
var TURN_MESSAGE_COLUMNS = {
|
|
426
|
+
id: agentMessage.id,
|
|
427
|
+
role: agentMessage.role,
|
|
428
|
+
content: agentMessage.content,
|
|
429
|
+
agentName: agentMessage.agentName,
|
|
430
|
+
toolCalls: agentMessage.toolCalls,
|
|
431
|
+
toolResults: agentMessage.toolResults,
|
|
432
|
+
attachments: agentMessage.attachments,
|
|
433
|
+
createdAt: agentMessage.createdAt
|
|
434
|
+
};
|
|
282
435
|
var DrizzleAgentStore = class {
|
|
283
436
|
static {
|
|
284
437
|
__name(this, "DrizzleAgentStore");
|
|
@@ -296,6 +449,7 @@ var DrizzleAgentStore = class {
|
|
|
296
449
|
title: input.title ?? "New chat",
|
|
297
450
|
transient: input.transient ?? false,
|
|
298
451
|
activeStreamId: null,
|
|
452
|
+
defaultAgent: null,
|
|
299
453
|
createdAt: now,
|
|
300
454
|
updatedAt: now,
|
|
301
455
|
deletedAt: null
|
|
@@ -318,6 +472,50 @@ var DrizzleAgentStore = class {
|
|
|
318
472
|
} : {}
|
|
319
473
|
};
|
|
320
474
|
}
|
|
475
|
+
/**
|
|
476
|
+
* The window a turn reads off a thread: its newest `messageLimit` messages (oldest first), the
|
|
477
|
+
* title, the default agent, and whether the thread has EVER been answered.
|
|
478
|
+
*
|
|
479
|
+
* {@link getThread} is the wrong read for a turn. It materializes the transcript — every message,
|
|
480
|
+
* every attachment, every tool output the thread ever recorded — and the run then journals what it
|
|
481
|
+
* loaded, so a long thread pays for its whole history on every turn and again on every replay.
|
|
482
|
+
*
|
|
483
|
+
* `hasAssistantMessage` is answered over the WHOLE thread, not the returned page: it answers "has
|
|
484
|
+
* this conversation been answered before?", and a thread whose window happens to hold only the
|
|
485
|
+
* user's last questions has still been answered. `null` when the thread is unknown or
|
|
486
|
+
* soft-deleted, same as {@link getThread}.
|
|
487
|
+
*/
|
|
488
|
+
async loadThreadForTurn(query) {
|
|
489
|
+
const [thread] = await this.db.select({
|
|
490
|
+
title: agentThread.title,
|
|
491
|
+
defaultAgent: agentThread.defaultAgent
|
|
492
|
+
}).from(agentThread).where((0, import_drizzle_orm2.and)((0, import_drizzle_orm2.eq)(agentThread.id, query.threadId), (0, import_drizzle_orm2.isNull)(agentThread.deletedAt)));
|
|
493
|
+
if (thread === void 0) {
|
|
494
|
+
return null;
|
|
495
|
+
}
|
|
496
|
+
const messages = await this.loadTurnWindow(query.threadId, query.messageLimit);
|
|
497
|
+
const [answered] = await this.db.select({
|
|
498
|
+
id: agentMessage.id
|
|
499
|
+
}).from(agentMessage).where((0, import_drizzle_orm2.and)((0, import_drizzle_orm2.eq)(agentMessage.threadId, query.threadId), (0, import_drizzle_orm2.eq)(agentMessage.role, "assistant"))).limit(1);
|
|
500
|
+
return {
|
|
501
|
+
title: thread.title,
|
|
502
|
+
defaultAgent: thread.defaultAgent,
|
|
503
|
+
hasAssistantMessage: answered !== void 0,
|
|
504
|
+
messages
|
|
505
|
+
};
|
|
506
|
+
}
|
|
507
|
+
/**
|
|
508
|
+
* The newest `limit` messages of a thread, oldest first, projected to the columns a model turn
|
|
509
|
+
* reads. Read newest-first so the LIMIT is the database's job, then reversed for the prompt.
|
|
510
|
+
*/
|
|
511
|
+
async loadTurnWindow(threadId, limit) {
|
|
512
|
+
if (limit !== void 0 && limit <= 0) {
|
|
513
|
+
return [];
|
|
514
|
+
}
|
|
515
|
+
const window = this.db.select(TURN_MESSAGE_COLUMNS).from(agentMessage).where((0, import_drizzle_orm2.eq)(agentMessage.threadId, threadId)).orderBy((0, import_drizzle_orm2.desc)(agentMessage.createdAt), (0, import_drizzle_orm2.desc)(agentMessage.id));
|
|
516
|
+
const rows = limit === void 0 ? await window : await window.limit(limit);
|
|
517
|
+
return rows.reverse().map((row) => this.toStoredMessage(row));
|
|
518
|
+
}
|
|
321
519
|
async listThreads(actorRef, limit = 50) {
|
|
322
520
|
const threads = await this.db.select().from(agentThread).where((0, import_drizzle_orm2.and)((0, import_drizzle_orm2.eq)(agentThread.actorRef, actorRef), (0, import_drizzle_orm2.eq)(agentThread.transient, false), (0, import_drizzle_orm2.isNull)(agentThread.deletedAt))).orderBy((0, import_drizzle_orm2.desc)(agentThread.updatedAt)).limit(limit);
|
|
323
521
|
const summaries = [];
|
|
@@ -348,6 +546,7 @@ var DrizzleAgentStore = class {
|
|
|
348
546
|
title: source.title,
|
|
349
547
|
transient: false,
|
|
350
548
|
activeStreamId: null,
|
|
549
|
+
defaultAgent: source.defaultAgent,
|
|
351
550
|
createdAt: now,
|
|
352
551
|
updatedAt: now,
|
|
353
552
|
deletedAt: null
|
|
@@ -361,9 +560,14 @@ var DrizzleAgentStore = class {
|
|
|
361
560
|
content: message.content,
|
|
362
561
|
toolCalls: message.toolCalls,
|
|
363
562
|
toolResults: message.toolResults,
|
|
563
|
+
attachments: message.attachments,
|
|
364
564
|
followUps: message.followUps,
|
|
365
565
|
usage: message.usage,
|
|
366
566
|
agentName: message.agentName,
|
|
567
|
+
// The copy is the same message, so it keeps the run that wrote it. A reader asking which
|
|
568
|
+
// turn produced this text gets the truthful answer; the run's own thread is still the
|
|
569
|
+
// original, so a run-scoped read never picks the fork's rows up.
|
|
570
|
+
runId: message.runId,
|
|
367
571
|
createdAt: message.createdAt
|
|
368
572
|
})));
|
|
369
573
|
}
|
|
@@ -383,9 +587,10 @@ var DrizzleAgentStore = class {
|
|
|
383
587
|
}
|
|
384
588
|
async runForToolCall(toolCallId) {
|
|
385
589
|
const [row] = await this.db.select({
|
|
590
|
+
runId: agentToolCall.runId,
|
|
386
591
|
activeStreamId: agentThread.activeStreamId
|
|
387
592
|
}).from(agentToolCall).innerJoin(agentMessage, (0, import_drizzle_orm2.eq)(agentToolCall.messageId, agentMessage.id)).innerJoin(agentThread, (0, import_drizzle_orm2.eq)(agentMessage.threadId, agentThread.id)).where((0, import_drizzle_orm2.eq)(agentToolCall.id, toolCallId));
|
|
388
|
-
return row?.activeStreamId ?? null;
|
|
593
|
+
return row?.runId ?? row?.activeStreamId ?? null;
|
|
389
594
|
}
|
|
390
595
|
async ownerOfActiveStream(runId) {
|
|
391
596
|
const [thread] = await this.db.select({
|
|
@@ -410,7 +615,43 @@ var DrizzleAgentStore = class {
|
|
|
410
615
|
activeStreamId: runId
|
|
411
616
|
}).where((0, import_drizzle_orm2.eq)(agentThread.id, threadId));
|
|
412
617
|
}
|
|
413
|
-
/**
|
|
618
|
+
/**
|
|
619
|
+
* Patch a thread's `title` and/or `defaultAgent`. Each field is only touched when PRESENT in
|
|
620
|
+
* `patch` — `defaultAgent: null` clears it (falls back to the app default), while an omitted
|
|
621
|
+
* `defaultAgent` leaves whatever is stored untouched. A no-op (including `updatedAt`) when the
|
|
622
|
+
* patch is empty or the thread doesn't exist.
|
|
623
|
+
*/
|
|
624
|
+
async updateThread(threadId, patch) {
|
|
625
|
+
const updates = {};
|
|
626
|
+
if (patch.title !== void 0) {
|
|
627
|
+
updates.title = patch.title;
|
|
628
|
+
}
|
|
629
|
+
if (patch.defaultAgent !== void 0) {
|
|
630
|
+
updates.defaultAgent = patch.defaultAgent;
|
|
631
|
+
}
|
|
632
|
+
if (Object.keys(updates).length === 0) {
|
|
633
|
+
return;
|
|
634
|
+
}
|
|
635
|
+
updates.updatedAt = /* @__PURE__ */ new Date();
|
|
636
|
+
await this.db.update(agentThread).set(updates).where((0, import_drizzle_orm2.eq)(agentThread.id, threadId));
|
|
637
|
+
}
|
|
638
|
+
/**
|
|
639
|
+
* The thread's default agent, projected — the caller wants one nullable scalar to decide which
|
|
640
|
+
* agent answers the next turn, and {@link getThread} would materialize the whole transcript to
|
|
641
|
+
* hand it over. `null` when the thread is unknown, soft-deleted, or has no default set.
|
|
642
|
+
*/
|
|
643
|
+
async defaultAgentForThread(threadId) {
|
|
644
|
+
const [thread] = await this.db.select({
|
|
645
|
+
defaultAgent: agentThread.defaultAgent
|
|
646
|
+
}).from(agentThread).where((0, import_drizzle_orm2.and)((0, import_drizzle_orm2.eq)(agentThread.id, threadId), (0, import_drizzle_orm2.isNull)(agentThread.deletedAt)));
|
|
647
|
+
return thread?.defaultAgent ?? null;
|
|
648
|
+
}
|
|
649
|
+
/**
|
|
650
|
+
* Persist the start of a run (turn). Replay-safe: called under a durable localStep.
|
|
651
|
+
*
|
|
652
|
+
* Takes the SPI's own {@link RecordRunStartInput} rather than a hand-copied shape: a field added
|
|
653
|
+
* to the input is otherwise accepted and dropped, silently, by every adapter that re-declares it.
|
|
654
|
+
*/
|
|
414
655
|
async recordRunStart(run) {
|
|
415
656
|
const runRow = {
|
|
416
657
|
id: run.runId,
|
|
@@ -424,7 +665,8 @@ var DrizzleAgentStore = class {
|
|
|
424
665
|
retries: 0,
|
|
425
666
|
startedAt: /* @__PURE__ */ new Date(),
|
|
426
667
|
settledAt: null,
|
|
427
|
-
promptHash: run.promptHash ?? null
|
|
668
|
+
promptHash: run.promptHash ?? null,
|
|
669
|
+
parentRunId: run.parentRunId ?? null
|
|
428
670
|
};
|
|
429
671
|
await this.db.insert(agentRun).values(runRow);
|
|
430
672
|
}
|
|
@@ -464,9 +706,11 @@ var DrizzleAgentStore = class {
|
|
|
464
706
|
content: input.content,
|
|
465
707
|
toolCalls: input.toolCalls ?? null,
|
|
466
708
|
toolResults: input.toolResults ?? null,
|
|
709
|
+
attachments: input.attachments ?? null,
|
|
467
710
|
followUps: input.followUps ?? null,
|
|
468
711
|
usage: input.usage ?? null,
|
|
469
712
|
agentName: input.agentName ?? null,
|
|
713
|
+
runId: input.runId ?? null,
|
|
470
714
|
createdAt: now
|
|
471
715
|
};
|
|
472
716
|
await this.db.insert(agentMessage).values(message);
|
|
@@ -475,6 +719,11 @@ var DrizzleAgentStore = class {
|
|
|
475
719
|
}).where((0, import_drizzle_orm2.eq)(agentThread.id, input.threadId));
|
|
476
720
|
return this.toStoredMessage(message);
|
|
477
721
|
}
|
|
722
|
+
async setMessageToolResults(messageId, results) {
|
|
723
|
+
await this.db.update(agentMessage).set({
|
|
724
|
+
toolResults: results
|
|
725
|
+
}).where((0, import_drizzle_orm2.eq)(agentMessage.id, messageId));
|
|
726
|
+
}
|
|
478
727
|
async truncateFrom(threadId, messageId) {
|
|
479
728
|
const messages = await this.db.select().from(agentMessage).where((0, import_drizzle_orm2.eq)(agentMessage.threadId, threadId)).orderBy((0, import_drizzle_orm2.asc)(agentMessage.createdAt), (0, import_drizzle_orm2.asc)(agentMessage.id));
|
|
480
729
|
const cutoff = messages.findIndex((message) => message.id === messageId);
|
|
@@ -523,6 +772,39 @@ var DrizzleAgentStore = class {
|
|
|
523
772
|
}
|
|
524
773
|
await this.db.update(agentToolCall).set(updates).where((0, import_drizzle_orm2.eq)(agentToolCall.id, input.toolCallId));
|
|
525
774
|
}
|
|
775
|
+
/**
|
|
776
|
+
* Of `mediaIds`, the ones a surviving message in one of this actor's threads still carries.
|
|
777
|
+
*
|
|
778
|
+
* Reads the `attachments` JSON back out and matches in memory rather than pushing the match into
|
|
779
|
+
* SQL: the column holds an array of objects, and every dialect this adapter's sibling targets
|
|
780
|
+
* spells that query differently (`jsonb` containment, `json_table`, `json_each`), while none of
|
|
781
|
+
* them can use an index for it anyway. The scan is bounded by ONE actor's attachment-bearing
|
|
782
|
+
* messages, which is a small set — attachments are rare, and a message without one is excluded
|
|
783
|
+
* by the `is not null` before any JSON is parsed.
|
|
784
|
+
*
|
|
785
|
+
* Soft-deleted threads are deliberately included: their message rows survive, so the bytes they
|
|
786
|
+
* point at are still reachable from stored state and are not garbage.
|
|
787
|
+
*/
|
|
788
|
+
async referencedMediaIds(actorRef, mediaIds) {
|
|
789
|
+
if (mediaIds.length === 0) {
|
|
790
|
+
return [];
|
|
791
|
+
}
|
|
792
|
+
const rows = await this.db.select({
|
|
793
|
+
attachments: agentMessage.attachments
|
|
794
|
+
}).from(agentMessage).innerJoin(agentThread, (0, import_drizzle_orm2.eq)(agentMessage.threadId, agentThread.id)).where((0, import_drizzle_orm2.and)((0, import_drizzle_orm2.eq)(agentThread.actorRef, actorRef), (0, import_drizzle_orm2.isNotNull)(agentMessage.attachments)));
|
|
795
|
+
const wanted = new Set(mediaIds);
|
|
796
|
+
const found = /* @__PURE__ */ new Set();
|
|
797
|
+
for (const row of rows) {
|
|
798
|
+
for (const attachment of row.attachments ?? []) {
|
|
799
|
+
if (wanted.has(attachment.mediaId)) {
|
|
800
|
+
found.add(attachment.mediaId);
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
return [
|
|
805
|
+
...wanted
|
|
806
|
+
].filter((mediaId) => found.has(mediaId));
|
|
807
|
+
}
|
|
526
808
|
async recordUsage(input) {
|
|
527
809
|
await this.db.insert(agentTokenUsage).values({
|
|
528
810
|
id: crypto.randomUUID(),
|
|
@@ -557,6 +839,7 @@ var DrizzleAgentStore = class {
|
|
|
557
839
|
transient: thread.transient,
|
|
558
840
|
createdAt: thread.createdAt.toISOString(),
|
|
559
841
|
updatedAt: thread.updatedAt.toISOString(),
|
|
842
|
+
defaultAgent: thread.defaultAgent,
|
|
560
843
|
...lastContent !== void 0 ? {
|
|
561
844
|
lastMessagePreview: lastContent.slice(0, 120)
|
|
562
845
|
} : {}
|
|
@@ -574,6 +857,9 @@ var DrizzleAgentStore = class {
|
|
|
574
857
|
...message.toolResults != null ? {
|
|
575
858
|
toolResults: message.toolResults
|
|
576
859
|
} : {},
|
|
860
|
+
...message.attachments != null ? {
|
|
861
|
+
attachments: message.attachments
|
|
862
|
+
} : {},
|
|
577
863
|
...message.followUps != null ? {
|
|
578
864
|
followUps: message.followUps
|
|
579
865
|
} : {},
|
|
@@ -582,6 +868,9 @@ var DrizzleAgentStore = class {
|
|
|
582
868
|
} : {},
|
|
583
869
|
...message.agentName != null ? {
|
|
584
870
|
agentName: message.agentName
|
|
871
|
+
} : {},
|
|
872
|
+
...message.runId != null ? {
|
|
873
|
+
runId: message.runId
|
|
585
874
|
} : {}
|
|
586
875
|
};
|
|
587
876
|
}
|
|
@@ -615,7 +904,8 @@ __name(isToolKind, "isToolKind");
|
|
|
615
904
|
var RUN_STATUSES = [
|
|
616
905
|
"running",
|
|
617
906
|
"completed",
|
|
618
|
-
"failed"
|
|
907
|
+
"failed",
|
|
908
|
+
"cancelled"
|
|
619
909
|
];
|
|
620
910
|
function isRunStatus(value) {
|
|
621
911
|
return RUN_STATUSES.includes(value);
|
|
@@ -656,7 +946,8 @@ function toRecentRunRow(run) {
|
|
|
656
946
|
errorMessage: run.errorMessage ?? null,
|
|
657
947
|
retries: run.retries,
|
|
658
948
|
startedAt: run.startedAt.toISOString(),
|
|
659
|
-
promptHash: run.promptHash ?? null
|
|
949
|
+
promptHash: run.promptHash ?? null,
|
|
950
|
+
parentRunId: run.parentRunId ?? null
|
|
660
951
|
};
|
|
661
952
|
}
|
|
662
953
|
__name(toRecentRunRow, "toRecentRunRow");
|
|
@@ -1236,8 +1527,150 @@ var DrizzleGovernanceQueries = class {
|
|
|
1236
1527
|
}
|
|
1237
1528
|
};
|
|
1238
1529
|
|
|
1239
|
-
// src/drizzle-
|
|
1530
|
+
// src/drizzle-memory-provider.ts
|
|
1531
|
+
var import_nestjs_agent_core2 = require("@dudousxd/nestjs-agent-core");
|
|
1240
1532
|
var import_drizzle_orm4 = require("drizzle-orm");
|
|
1533
|
+
function toRecord(row) {
|
|
1534
|
+
return {
|
|
1535
|
+
id: row.id,
|
|
1536
|
+
key: row.key,
|
|
1537
|
+
text: row.text,
|
|
1538
|
+
scope: row.scope,
|
|
1539
|
+
origin: {
|
|
1540
|
+
author: row.originAuthor,
|
|
1541
|
+
...row.originThreadId !== null ? {
|
|
1542
|
+
threadId: row.originThreadId
|
|
1543
|
+
} : {},
|
|
1544
|
+
...row.originRunId !== null ? {
|
|
1545
|
+
runId: row.originRunId
|
|
1546
|
+
} : {},
|
|
1547
|
+
...row.originActorRef !== null ? {
|
|
1548
|
+
actorRef: row.originActorRef
|
|
1549
|
+
} : {}
|
|
1550
|
+
},
|
|
1551
|
+
updatedAt: row.updatedAt.toISOString(),
|
|
1552
|
+
pinned: row.pinned
|
|
1553
|
+
};
|
|
1554
|
+
}
|
|
1555
|
+
__name(toRecord, "toRecord");
|
|
1556
|
+
var DrizzleMemoryProvider = class {
|
|
1557
|
+
static {
|
|
1558
|
+
__name(this, "DrizzleMemoryProvider");
|
|
1559
|
+
}
|
|
1560
|
+
db;
|
|
1561
|
+
constructor(db) {
|
|
1562
|
+
this.db = db;
|
|
1563
|
+
}
|
|
1564
|
+
/**
|
|
1565
|
+
* Every memory visible at `scopes` — asked on EVERY turn, so it is one indexed `scope in (…)`
|
|
1566
|
+
* against the leading column of the (`scope`, `key`) unique index.
|
|
1567
|
+
*
|
|
1568
|
+
* The scope filter is in the QUERY. The library drops out-of-scope records it is handed, but that
|
|
1569
|
+
* is a backstop: a memory held for another actor or another tenant is never selected here, so it
|
|
1570
|
+
* is unreachable rather than outranked.
|
|
1571
|
+
*/
|
|
1572
|
+
async list({ scopes }) {
|
|
1573
|
+
if (scopes.length === 0) {
|
|
1574
|
+
return [];
|
|
1575
|
+
}
|
|
1576
|
+
const rows = await this.db.select().from(agentMemory).where((0, import_drizzle_orm4.inArray)(agentMemory.scope, [
|
|
1577
|
+
...scopes
|
|
1578
|
+
]));
|
|
1579
|
+
return rows.map(toRecord);
|
|
1580
|
+
}
|
|
1581
|
+
/**
|
|
1582
|
+
* Delete one, and only from the actor's OWN scope.
|
|
1583
|
+
*
|
|
1584
|
+
* `memoryForgetVerdict` already holds the library's endpoint to that rule; the `where` repeats it
|
|
1585
|
+
* because `forget` takes an id and nothing else, so a caller reaching this provider by any other
|
|
1586
|
+
* path would otherwise delete a tenant's or the deployment's memory by knowing one id.
|
|
1587
|
+
*
|
|
1588
|
+
* `false` where nothing matched — which covers "no such id" and "not yours" identically, so the
|
|
1589
|
+
* answer cannot be used to find out which memories exist about other people.
|
|
1590
|
+
*/
|
|
1591
|
+
async forget({ id, ctx }) {
|
|
1592
|
+
const deleted = await this.db.delete(agentMemory).where((0, import_drizzle_orm4.and)((0, import_drizzle_orm4.eq)(agentMemory.id, id), (0, import_drizzle_orm4.eq)(agentMemory.scope, (0, import_nestjs_agent_core2.actorScope)(ctx.actor)))).returning({
|
|
1593
|
+
id: agentMemory.id
|
|
1594
|
+
});
|
|
1595
|
+
return deleted.length > 0;
|
|
1596
|
+
}
|
|
1597
|
+
/**
|
|
1598
|
+
* Upsert on (`scope`, `key`) — one statement, against the unique index, rather than a read
|
|
1599
|
+
* followed by a write: two turns concluding the same key at once would otherwise race to a
|
|
1600
|
+
* duplicate-key insert and one of them would fail the `remember` tool.
|
|
1601
|
+
*
|
|
1602
|
+
* The conflict `set` names exactly what a rewrite may change, so `pinned`, `createdAt` and `id`
|
|
1603
|
+
* are left alone by construction rather than by an exclusion anyone could forget to extend.
|
|
1604
|
+
* Dropping `pinned` would silently unpin a row the next time the agent restated the fact;
|
|
1605
|
+
* rewriting `createdAt` would lose when the belief was first formed; reassigning `id` would
|
|
1606
|
+
* invalidate the delete handle a person was already shown.
|
|
1607
|
+
*/
|
|
1608
|
+
async write({ key, text: text2, scope, origin, ctx }) {
|
|
1609
|
+
assertAuthorMayWriteScope({
|
|
1610
|
+
scope,
|
|
1611
|
+
origin,
|
|
1612
|
+
ctx
|
|
1613
|
+
});
|
|
1614
|
+
const now = /* @__PURE__ */ new Date();
|
|
1615
|
+
const columns = {
|
|
1616
|
+
originAuthor: origin.author,
|
|
1617
|
+
originThreadId: origin.threadId ?? null,
|
|
1618
|
+
originRunId: origin.runId ?? null,
|
|
1619
|
+
originActorRef: origin.actorRef ?? null
|
|
1620
|
+
};
|
|
1621
|
+
const [row] = await this.db.insert(agentMemory).values({
|
|
1622
|
+
id: crypto.randomUUID(),
|
|
1623
|
+
scope,
|
|
1624
|
+
key,
|
|
1625
|
+
text: text2,
|
|
1626
|
+
...columns,
|
|
1627
|
+
pinned: false,
|
|
1628
|
+
createdAt: now,
|
|
1629
|
+
updatedAt: now
|
|
1630
|
+
}).onConflictDoUpdate({
|
|
1631
|
+
target: [
|
|
1632
|
+
agentMemory.scope,
|
|
1633
|
+
agentMemory.key
|
|
1634
|
+
],
|
|
1635
|
+
set: {
|
|
1636
|
+
text: text2,
|
|
1637
|
+
...columns,
|
|
1638
|
+
updatedAt: now
|
|
1639
|
+
}
|
|
1640
|
+
}).returning();
|
|
1641
|
+
if (row === void 0) {
|
|
1642
|
+
throw new Error(`DrizzleMemoryProvider: the upsert of "${key}" at "${scope}" returned no row; the driver does not support RETURNING on conflict.`);
|
|
1643
|
+
}
|
|
1644
|
+
return toRecord(row);
|
|
1645
|
+
}
|
|
1646
|
+
/**
|
|
1647
|
+
* Make one memory always-on, or stop it being one. The operator act the SPI has no method for, on
|
|
1648
|
+
* purpose: a pin grants a fact a permanent place in every future prompt, so nothing an agent can
|
|
1649
|
+
* reach may set it. Authorize it in your own console — this takes no `ScopeContext` because it is
|
|
1650
|
+
* not an actor's act on their own memory.
|
|
1651
|
+
*
|
|
1652
|
+
* `false` where there is no such id.
|
|
1653
|
+
*/
|
|
1654
|
+
async pin({ id, pinned }) {
|
|
1655
|
+
const updated = await this.db.update(agentMemory).set({
|
|
1656
|
+
pinned,
|
|
1657
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
1658
|
+
}).where((0, import_drizzle_orm4.eq)(agentMemory.id, id)).returning({
|
|
1659
|
+
id: agentMemory.id
|
|
1660
|
+
});
|
|
1661
|
+
return updated.length > 0;
|
|
1662
|
+
}
|
|
1663
|
+
};
|
|
1664
|
+
function assertAuthorMayWriteScope({ scope, origin, ctx }) {
|
|
1665
|
+
const own = (0, import_nestjs_agent_core2.actorScope)(ctx.actor);
|
|
1666
|
+
if (origin.author !== "human" && scope !== own) {
|
|
1667
|
+
throw new Error(`DrizzleMemoryProvider: refusing to write an agent-authored memory at "${scope}"; an agent may write only at "${own}"`);
|
|
1668
|
+
}
|
|
1669
|
+
}
|
|
1670
|
+
__name(assertAuthorMayWriteScope, "assertAuthorMayWriteScope");
|
|
1671
|
+
|
|
1672
|
+
// src/drizzle-pricing-store.ts
|
|
1673
|
+
var import_drizzle_orm5 = require("drizzle-orm");
|
|
1241
1674
|
var DrizzlePricingStore = class {
|
|
1242
1675
|
static {
|
|
1243
1676
|
__name(this, "DrizzlePricingStore");
|
|
@@ -1249,7 +1682,7 @@ var DrizzlePricingStore = class {
|
|
|
1249
1682
|
async upsertModelPrice(input) {
|
|
1250
1683
|
await this.db.update(agentModelPricing).set({
|
|
1251
1684
|
isCurrent: false
|
|
1252
|
-
}).where((0,
|
|
1685
|
+
}).where((0, import_drizzle_orm5.and)((0, import_drizzle_orm5.eq)(agentModelPricing.modelId, input.modelId), (0, import_drizzle_orm5.eq)(agentModelPricing.isCurrent, true)));
|
|
1253
1686
|
await this.db.insert(agentModelPricing).values({
|
|
1254
1687
|
id: crypto.randomUUID(),
|
|
1255
1688
|
modelId: input.modelId,
|
|
@@ -1262,7 +1695,7 @@ var DrizzlePricingStore = class {
|
|
|
1262
1695
|
});
|
|
1263
1696
|
}
|
|
1264
1697
|
async listCurrentPrices() {
|
|
1265
|
-
const rows = await this.db.select().from(agentModelPricing).where((0,
|
|
1698
|
+
const rows = await this.db.select().from(agentModelPricing).where((0, import_drizzle_orm5.eq)(agentModelPricing.isCurrent, true));
|
|
1266
1699
|
return rows.map((row) => ({
|
|
1267
1700
|
modelId: row.modelId,
|
|
1268
1701
|
inputPricePer1m: row.inputPricePer1m,
|
|
@@ -1278,33 +1711,367 @@ var DrizzlePricingStore = class {
|
|
|
1278
1711
|
}
|
|
1279
1712
|
};
|
|
1280
1713
|
|
|
1281
|
-
// src/drizzle-
|
|
1282
|
-
var
|
|
1714
|
+
// src/drizzle-rag-ingestion-log.ts
|
|
1715
|
+
var import_node_diagnostics_channel = require("diagnostics_channel");
|
|
1283
1716
|
var import_common = require("@nestjs/common");
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1717
|
+
var import_drizzle_orm6 = require("drizzle-orm");
|
|
1718
|
+
function _ts_decorate(decorators, target, key, desc4) {
|
|
1719
|
+
var c = arguments.length, r = c < 3 ? target : desc4 === null ? desc4 = Object.getOwnPropertyDescriptor(target, key) : desc4, d;
|
|
1720
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc4);
|
|
1287
1721
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
1288
1722
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1289
1723
|
}
|
|
1290
1724
|
__name(_ts_decorate, "_ts_decorate");
|
|
1725
|
+
function _ts_metadata(k, v) {
|
|
1726
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
1727
|
+
}
|
|
1728
|
+
__name(_ts_metadata, "_ts_metadata");
|
|
1729
|
+
var CHANNELS = [
|
|
1730
|
+
{
|
|
1731
|
+
name: "aviary:rag:media.ingested",
|
|
1732
|
+
status: "ingested"
|
|
1733
|
+
},
|
|
1734
|
+
{
|
|
1735
|
+
name: "aviary:rag:media.skipped",
|
|
1736
|
+
status: "skipped"
|
|
1737
|
+
},
|
|
1738
|
+
{
|
|
1739
|
+
name: "aviary:rag:media.failed",
|
|
1740
|
+
status: "failed"
|
|
1741
|
+
},
|
|
1742
|
+
{
|
|
1743
|
+
name: "aviary:rag:media.removed",
|
|
1744
|
+
status: "removed"
|
|
1745
|
+
}
|
|
1746
|
+
];
|
|
1747
|
+
function str(value) {
|
|
1748
|
+
return typeof value === "string" && value.length > 0 ? value : null;
|
|
1749
|
+
}
|
|
1750
|
+
__name(str, "str");
|
|
1751
|
+
function num(value) {
|
|
1752
|
+
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
1753
|
+
}
|
|
1754
|
+
__name(num, "num");
|
|
1755
|
+
var RAG_INGESTION_LOG_PAGE_ORDER = [
|
|
1756
|
+
(0, import_drizzle_orm6.desc)(ragIngestionLog.updatedAt),
|
|
1757
|
+
(0, import_drizzle_orm6.asc)(ragIngestionLog.documentId)
|
|
1758
|
+
];
|
|
1759
|
+
var DEFAULT_PAGE_SIZE = 200;
|
|
1760
|
+
var DEFAULT_BATCH_SIZE = 200;
|
|
1761
|
+
function batches(batchSize) {
|
|
1762
|
+
const requested = Math.trunc(batchSize ?? DEFAULT_BATCH_SIZE);
|
|
1763
|
+
return Number.isFinite(requested) && requested >= 1 ? requested : DEFAULT_BATCH_SIZE;
|
|
1764
|
+
}
|
|
1765
|
+
__name(batches, "batches");
|
|
1766
|
+
var CURSOR_COLUMNS = {
|
|
1767
|
+
documentId: ragIngestionLog.documentId,
|
|
1768
|
+
updatedAt: ragIngestionLog.updatedAt
|
|
1769
|
+
};
|
|
1770
|
+
var DrizzleRagIngestionLog = class _DrizzleRagIngestionLog {
|
|
1771
|
+
static {
|
|
1772
|
+
__name(this, "DrizzleRagIngestionLog");
|
|
1773
|
+
}
|
|
1774
|
+
db;
|
|
1775
|
+
logger = new import_common.Logger(_DrizzleRagIngestionLog.name);
|
|
1776
|
+
teardowns = [];
|
|
1777
|
+
inFlight = /* @__PURE__ */ new Set();
|
|
1778
|
+
constructor(db) {
|
|
1779
|
+
this.db = db;
|
|
1780
|
+
}
|
|
1781
|
+
onModuleInit() {
|
|
1782
|
+
for (const channel of CHANNELS) {
|
|
1783
|
+
const listener = /* @__PURE__ */ __name((message) => {
|
|
1784
|
+
const payload = message?.payload;
|
|
1785
|
+
if (payload !== void 0) {
|
|
1786
|
+
this.track(this.record(channel.status, payload));
|
|
1787
|
+
}
|
|
1788
|
+
}, "listener");
|
|
1789
|
+
(0, import_node_diagnostics_channel.subscribe)(channel.name, listener);
|
|
1790
|
+
this.teardowns.push(() => (0, import_node_diagnostics_channel.unsubscribe)(channel.name, listener));
|
|
1791
|
+
}
|
|
1792
|
+
}
|
|
1793
|
+
async onModuleDestroy() {
|
|
1794
|
+
for (const teardown of this.teardowns) {
|
|
1795
|
+
teardown();
|
|
1796
|
+
}
|
|
1797
|
+
this.teardowns = [];
|
|
1798
|
+
await this.settle();
|
|
1799
|
+
}
|
|
1800
|
+
/** Await every in-flight write — for graceful shutdown and deterministic tests. */
|
|
1801
|
+
async settle() {
|
|
1802
|
+
await Promise.allSettled([
|
|
1803
|
+
...this.inFlight
|
|
1804
|
+
]);
|
|
1805
|
+
}
|
|
1806
|
+
/** The latest recorded outcome per document, newest first. */
|
|
1807
|
+
async list(query = {}) {
|
|
1808
|
+
const rows = this.db.select().from(ragIngestionLog).where(this.where(query)).orderBy(...RAG_INGESTION_LOG_PAGE_ORDER).limit(query.limit ?? DEFAULT_PAGE_SIZE);
|
|
1809
|
+
return query.offset === void 0 ? rows : rows.offset(query.offset);
|
|
1810
|
+
}
|
|
1811
|
+
/**
|
|
1812
|
+
* The same page plus the unpaginated total, so a caller can tell "these are all of them" from
|
|
1813
|
+
* "these are the first N". A list that silently truncates reads as complete when it isn't.
|
|
1814
|
+
*
|
|
1815
|
+
* Offset paging is only sound over a table nobody is deleting from underneath you: a row removed
|
|
1816
|
+
* behind the cursor shifts everything after it back by one, so the next page starts one row late
|
|
1817
|
+
* and that row is never seen. Use {@link iterate} for any sweep that deletes.
|
|
1818
|
+
*/
|
|
1819
|
+
async listPage(query = {}) {
|
|
1820
|
+
const [totalRow] = await this.db.select({
|
|
1821
|
+
value: (0, import_drizzle_orm6.count)()
|
|
1822
|
+
}).from(ragIngestionLog).where(this.where(query));
|
|
1823
|
+
return {
|
|
1824
|
+
rows: await this.list(query),
|
|
1825
|
+
total: totalRow?.value ?? 0
|
|
1826
|
+
};
|
|
1827
|
+
}
|
|
1828
|
+
/**
|
|
1829
|
+
* Every matching row, newest first, streamed in batches — the sweep-safe way to walk this table.
|
|
1830
|
+
*
|
|
1831
|
+
* Paging is *keyset*, not offset: each batch asks for the rows that sort strictly after the last
|
|
1832
|
+
* row yielded, using `(updatedAt, documentId)` — one point in
|
|
1833
|
+
* {@link RAG_INGESTION_LOG_PAGE_ORDER}, which is total because it ends in the primary key. A
|
|
1834
|
+
* cursor made of column values does not move when rows leave the table, which is what makes this
|
|
1835
|
+
* delete-safe *by construction* rather than by the caller carefully advancing an offset by only
|
|
1836
|
+
* the rows it kept.
|
|
1837
|
+
*
|
|
1838
|
+
* **The guarantee, stated once:** a row is yielded exactly when — at the moment the batch that
|
|
1839
|
+
* would contain it is fetched — the row exists, matches `where`, and sorts strictly after the
|
|
1840
|
+
* last row already yielded. Everything below is a consequence of that one sentence.
|
|
1841
|
+
*
|
|
1842
|
+
* What you can rely on:
|
|
1843
|
+
* - **Deleting rows while iterating is safe.** Delete any row you like — the one just yielded, the
|
|
1844
|
+
* whole batch, rows you have not reached yet — and every row that is still there when the sweep
|
|
1845
|
+
* reaches its position is visited exactly once. Nothing is skipped and nothing is repeated,
|
|
1846
|
+
* because deleting a row moves no *other* row's `(updatedAt, documentId)`. (Rows you delete
|
|
1847
|
+
* *ahead* of the cursor are simply never visited, which is the point of deleting them.)
|
|
1848
|
+
* - **Ties are safe.** A bulk upload stamps a whole batch with the same `updatedAt`; the
|
|
1849
|
+
* `documentId` tiebreaker keeps consecutive batches disjoint even when every row ties.
|
|
1850
|
+
* - **Each row is yielded at most once**, for as long as `updatedAt` only ever moves forward —
|
|
1851
|
+
* which is what `record()` does, since it always stamps `now`.
|
|
1852
|
+
*
|
|
1853
|
+
* What this is **not**: a snapshot, or a repeatable read. The sweep observes the table as it is
|
|
1854
|
+
* when each batch is fetched, so:
|
|
1855
|
+
* - A row **inserted** mid-sweep by `record()` is stamped `now`. The order is newest-first, so it
|
|
1856
|
+
* sorts ahead of a cursor the sweep has already moved past, and is not visited. A sweep
|
|
1857
|
+
* therefore never sees documents ingested after it started — the behaviour an orphan sweep
|
|
1858
|
+
* wants, since a document that arrived while you were sweeping is not an orphan. (A *direct*
|
|
1859
|
+
* insert with a backdated `updatedAt` lands ahead of the cursor and **is** visited; nothing in
|
|
1860
|
+
* this class writes one.)
|
|
1861
|
+
* - A row **re-ingested** mid-sweep has its `updatedAt` bumped to `now`, moving it ahead of the
|
|
1862
|
+
* cursor for the same reason. If the sweep had already passed it, it is not visited twice; if it
|
|
1863
|
+
* had not, it is **missed for this pass**. That is the honest limit: against a concurrent
|
|
1864
|
+
* writer `iterate` guarantees "at most once", not "at least once". Sweeps that must not miss a
|
|
1865
|
+
* concurrently-rewritten row should be idempotent and run again.
|
|
1866
|
+
* - Only a row whose `updatedAt` moves *backwards* — which needs a direct write — can be yielded
|
|
1867
|
+
* twice.
|
|
1868
|
+
* - `collection` / `status` are re-evaluated per batch, so a row that stops matching mid-sweep
|
|
1869
|
+
* stops being visited.
|
|
1870
|
+
*
|
|
1871
|
+
* There is no `limit`/`offset` here on purpose: `where` says *which* rows, `options` says how the
|
|
1872
|
+
* sweep is run. A sweep that stops early stops by `break`ing out of the `for await`.
|
|
1873
|
+
*/
|
|
1874
|
+
iterate(where = {}, options = {}) {
|
|
1875
|
+
return this.sweep(where, batches(options.batchSize), options.after, (filter, limit) => this.db.select().from(ragIngestionLog).where(filter).orderBy(...RAG_INGESTION_LOG_PAGE_ORDER).limit(limit));
|
|
1876
|
+
}
|
|
1877
|
+
/**
|
|
1878
|
+
* Just the document ids of the matching rows, in {@link RAG_INGESTION_LOG_PAGE_ORDER}.
|
|
1879
|
+
*
|
|
1880
|
+
* Returns **all** of them — no 200-row cap, unlike `list` — by sweeping on {@link iterate}'s
|
|
1881
|
+
* keyset internally, so it is correct against concurrent deletes for the same reason `iterate`
|
|
1882
|
+
* is. What the cap protects against is hydrating an unbounded number of wide rows (`error` is a
|
|
1883
|
+
* TEXT column); this selects two columns — the id, plus the `updatedAt` the cursor needs — and
|
|
1884
|
+
* keeps only the ids, so the peak footprint is one batch of two-column rows plus a list of
|
|
1885
|
+
* strings whose size *is* the answer the caller asked for.
|
|
1886
|
+
*
|
|
1887
|
+
* For callers that need the id set of a collection and nothing else: an orphan sweep unioning the
|
|
1888
|
+
* log against the vector store's own document list.
|
|
1889
|
+
*/
|
|
1890
|
+
async listDocumentIds(where = {}, options = {}) {
|
|
1891
|
+
const ids = [];
|
|
1892
|
+
const rows = this.sweep(where, batches(options.batchSize), void 0, (filter, limit) => this.db.select(CURSOR_COLUMNS).from(ragIngestionLog).where(filter).orderBy(...RAG_INGESTION_LOG_PAGE_ORDER).limit(limit));
|
|
1893
|
+
for await (const row of rows) {
|
|
1894
|
+
ids.push(row.documentId);
|
|
1895
|
+
}
|
|
1896
|
+
return ids;
|
|
1897
|
+
}
|
|
1898
|
+
/** The latest recorded outcome for one document, or null if it was never attempted. */
|
|
1899
|
+
async get(documentId) {
|
|
1900
|
+
const [row] = await this.db.select().from(ragIngestionLog).where((0, import_drizzle_orm6.eq)(ragIngestionLog.documentId, documentId));
|
|
1901
|
+
return row ?? null;
|
|
1902
|
+
}
|
|
1903
|
+
/** Forget one document's record. Returns whether a row was actually removed. */
|
|
1904
|
+
async remove(documentId) {
|
|
1905
|
+
const removed = await this.db.delete(ragIngestionLog).where((0, import_drizzle_orm6.eq)(ragIngestionLog.documentId, documentId)).returning({
|
|
1906
|
+
documentId: ragIngestionLog.documentId
|
|
1907
|
+
});
|
|
1908
|
+
return removed.length > 0;
|
|
1909
|
+
}
|
|
1910
|
+
/** Forget every record for a collection — for when the collection itself is deleted. */
|
|
1911
|
+
async removeByCollection(collection) {
|
|
1912
|
+
const removed = await this.db.delete(ragIngestionLog).where((0, import_drizzle_orm6.eq)(ragIngestionLog.collection, collection)).returning({
|
|
1913
|
+
documentId: ragIngestionLog.documentId
|
|
1914
|
+
});
|
|
1915
|
+
return removed.length;
|
|
1916
|
+
}
|
|
1917
|
+
/**
|
|
1918
|
+
* The keyset sweep both {@link iterate} and {@link listDocumentIds} are made of. `page` decides
|
|
1919
|
+
* how wide a row is — whole rows for `iterate`, two columns for `listDocumentIds` — and the
|
|
1920
|
+
* `R extends RagIngestionLogCursor` bound says the only thing the sweep needs back: a row it can
|
|
1921
|
+
* read the next cursor off.
|
|
1922
|
+
*
|
|
1923
|
+
* The cursor advances **per yielded row**, not per batch, so a consumer that `break`s mid-batch
|
|
1924
|
+
* leaves it on the last row it actually saw. It is two column values read off that row, so a row
|
|
1925
|
+
* leaving the table cannot move it — the whole reason this is delete-safe by construction.
|
|
1926
|
+
*/
|
|
1927
|
+
async *sweep(where, batchSize, after, page) {
|
|
1928
|
+
let cursor = after;
|
|
1929
|
+
for (; ; ) {
|
|
1930
|
+
const rows = await page(this.keyset(where, cursor), batchSize);
|
|
1931
|
+
if (rows.length === 0) {
|
|
1932
|
+
return;
|
|
1933
|
+
}
|
|
1934
|
+
for (const row of rows) {
|
|
1935
|
+
yield row;
|
|
1936
|
+
cursor = {
|
|
1937
|
+
updatedAt: row.updatedAt,
|
|
1938
|
+
documentId: row.documentId
|
|
1939
|
+
};
|
|
1940
|
+
}
|
|
1941
|
+
}
|
|
1942
|
+
}
|
|
1943
|
+
where(query) {
|
|
1944
|
+
return (0, import_drizzle_orm6.and)(query.collection !== void 0 ? (0, import_drizzle_orm6.eq)(ragIngestionLog.collection, query.collection) : void 0, query.status !== void 0 ? (0, import_drizzle_orm6.eq)(ragIngestionLog.status, query.status) : void 0);
|
|
1945
|
+
}
|
|
1946
|
+
/**
|
|
1947
|
+
* The coordinates filter AND'd with "strictly after `cursor` in
|
|
1948
|
+
* {@link RAG_INGESTION_LOG_PAGE_ORDER}".
|
|
1949
|
+
*
|
|
1950
|
+
* The order is `updatedAt desc, documentId asc`, so "after" means an older timestamp, or the same
|
|
1951
|
+
* timestamp and a larger id. Both halves are needed: the `<` alone would re-yield every row tied
|
|
1952
|
+
* with the cursor, and dropping the tie branch would skip them instead.
|
|
1953
|
+
*/
|
|
1954
|
+
keyset(where, cursor) {
|
|
1955
|
+
const base = this.where(where);
|
|
1956
|
+
if (cursor === void 0) {
|
|
1957
|
+
return base;
|
|
1958
|
+
}
|
|
1959
|
+
return (0, import_drizzle_orm6.and)(base, (0, import_drizzle_orm6.or)((0, import_drizzle_orm6.lt)(ragIngestionLog.updatedAt, cursor.updatedAt), (0, import_drizzle_orm6.and)((0, import_drizzle_orm6.eq)(ragIngestionLog.updatedAt, cursor.updatedAt), (0, import_drizzle_orm6.gt)(ragIngestionLog.documentId, cursor.documentId))));
|
|
1960
|
+
}
|
|
1961
|
+
/**
|
|
1962
|
+
* Upsert one outcome. Keyed by document id so the row always reflects the *current* state — a
|
|
1963
|
+
* retry that succeeds overwrites the failure it replaces, rather than leaving a stale error next
|
|
1964
|
+
* to a working document.
|
|
1965
|
+
*/
|
|
1966
|
+
async record(status, payload) {
|
|
1967
|
+
const documentId = str(payload.mediaId);
|
|
1968
|
+
if (documentId === null) {
|
|
1969
|
+
return;
|
|
1970
|
+
}
|
|
1971
|
+
try {
|
|
1972
|
+
const now = /* @__PURE__ */ new Date();
|
|
1973
|
+
const collection = str(payload.collection);
|
|
1974
|
+
const ownerType = str(payload.ownerType);
|
|
1975
|
+
const ownerId = str(payload.ownerId);
|
|
1976
|
+
const source = str(payload.source);
|
|
1977
|
+
const mimeType = str(payload.mimeType);
|
|
1978
|
+
const size = num(payload.size);
|
|
1979
|
+
const outcome = {
|
|
1980
|
+
status,
|
|
1981
|
+
// The three outcome-specific columns are exclusive: null out the ones this status doesn't
|
|
1982
|
+
// own on every write, so a successful retry clears the previous attempt's error rather than
|
|
1983
|
+
// leaving it next to a working document. Always present → always in the conflict `set`.
|
|
1984
|
+
chunks: status === "ingested" ? num(payload.chunks) : null,
|
|
1985
|
+
reason: status === "skipped" ? str(payload.reason) : null,
|
|
1986
|
+
error: status === "failed" ? str(payload.error) : null,
|
|
1987
|
+
updatedAt: now,
|
|
1988
|
+
...collection !== null ? {
|
|
1989
|
+
collection
|
|
1990
|
+
} : {},
|
|
1991
|
+
...ownerType !== null ? {
|
|
1992
|
+
ownerType
|
|
1993
|
+
} : {},
|
|
1994
|
+
...ownerId !== null ? {
|
|
1995
|
+
ownerId
|
|
1996
|
+
} : {},
|
|
1997
|
+
...source !== null ? {
|
|
1998
|
+
source
|
|
1999
|
+
} : {},
|
|
2000
|
+
...mimeType !== null ? {
|
|
2001
|
+
mimeType
|
|
2002
|
+
} : {},
|
|
2003
|
+
...size !== null ? {
|
|
2004
|
+
size
|
|
2005
|
+
} : {}
|
|
2006
|
+
};
|
|
2007
|
+
await this.db.insert(ragIngestionLog).values({
|
|
2008
|
+
documentId,
|
|
2009
|
+
createdAt: now,
|
|
2010
|
+
...outcome
|
|
2011
|
+
}).onConflictDoUpdate({
|
|
2012
|
+
target: ragIngestionLog.documentId,
|
|
2013
|
+
set: outcome
|
|
2014
|
+
});
|
|
2015
|
+
} catch (error) {
|
|
2016
|
+
this.logger.warn(`Could not record RAG ingestion outcome for ${documentId}: ${error instanceof Error ? error.message : String(error)}`);
|
|
2017
|
+
}
|
|
2018
|
+
}
|
|
2019
|
+
track(promise) {
|
|
2020
|
+
const tracked = promise.finally(() => {
|
|
2021
|
+
this.inFlight.delete(tracked);
|
|
2022
|
+
});
|
|
2023
|
+
this.inFlight.add(tracked);
|
|
2024
|
+
}
|
|
2025
|
+
};
|
|
2026
|
+
DrizzleRagIngestionLog = _ts_decorate([
|
|
2027
|
+
(0, import_common.Injectable)(),
|
|
2028
|
+
_ts_metadata("design:type", Function),
|
|
2029
|
+
_ts_metadata("design:paramtypes", [
|
|
2030
|
+
typeof AgentDrizzleDb === "undefined" ? Object : AgentDrizzleDb
|
|
2031
|
+
])
|
|
2032
|
+
], DrizzleRagIngestionLog);
|
|
2033
|
+
|
|
2034
|
+
// src/drizzle-agent-store.module.ts
|
|
2035
|
+
var import_nestjs_agent_core3 = require("@dudousxd/nestjs-agent-core");
|
|
2036
|
+
var import_common2 = require("@nestjs/common");
|
|
2037
|
+
function _ts_decorate2(decorators, target, key, desc4) {
|
|
2038
|
+
var c = arguments.length, r = c < 3 ? target : desc4 === null ? desc4 = Object.getOwnPropertyDescriptor(target, key) : desc4, d;
|
|
2039
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc4);
|
|
2040
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
2041
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
2042
|
+
}
|
|
2043
|
+
__name(_ts_decorate2, "_ts_decorate");
|
|
1291
2044
|
var DrizzleAgentStoreModule = class _DrizzleAgentStoreModule {
|
|
1292
2045
|
static {
|
|
1293
2046
|
__name(this, "DrizzleAgentStoreModule");
|
|
1294
2047
|
}
|
|
1295
2048
|
static forRoot(options) {
|
|
2049
|
+
const ragProviders = options.ragIngestionLog === false ? [] : [
|
|
2050
|
+
{
|
|
2051
|
+
provide: DrizzleRagIngestionLog,
|
|
2052
|
+
useFactory: /* @__PURE__ */ __name(() => new DrizzleRagIngestionLog(options.db), "useFactory")
|
|
2053
|
+
}
|
|
2054
|
+
];
|
|
1296
2055
|
return {
|
|
1297
2056
|
module: _DrizzleAgentStoreModule,
|
|
1298
2057
|
global: true,
|
|
1299
2058
|
providers: [
|
|
2059
|
+
...ragProviders,
|
|
1300
2060
|
{
|
|
1301
2061
|
provide: DrizzleAgentStore,
|
|
1302
2062
|
useFactory: /* @__PURE__ */ __name(() => new DrizzleAgentStore(options.db), "useFactory")
|
|
1303
2063
|
},
|
|
1304
2064
|
{
|
|
1305
|
-
provide:
|
|
2065
|
+
provide: import_nestjs_agent_core3.AGENT_STORE,
|
|
1306
2066
|
useExisting: DrizzleAgentStore
|
|
1307
2067
|
},
|
|
2068
|
+
// Exported, never bound to AGENT_MEMORY: that token's PRESENCE is what turns memory on, so
|
|
2069
|
+
// binding it here would switch the feature on for every host that installs the store. A
|
|
2070
|
+
// host opts in by naming this provider in `AgentModule.forRoot({ memory: { provider } })`.
|
|
2071
|
+
{
|
|
2072
|
+
provide: DrizzleMemoryProvider,
|
|
2073
|
+
useFactory: /* @__PURE__ */ __name(() => new DrizzleMemoryProvider(options.db), "useFactory")
|
|
2074
|
+
},
|
|
1308
2075
|
{
|
|
1309
2076
|
provide: DrizzlePricingStore,
|
|
1310
2077
|
useFactory: /* @__PURE__ */ __name(() => new DrizzlePricingStore(options.db), "useFactory")
|
|
@@ -1312,44 +2079,52 @@ var DrizzleAgentStoreModule = class _DrizzleAgentStoreModule {
|
|
|
1312
2079
|
// AGENT_PRICING_STORE: the host's own store when supplied, else the default Drizzle one.
|
|
1313
2080
|
// DrizzleGovernanceQueries prices usage against whatever is bound here.
|
|
1314
2081
|
options.pricingStore ? {
|
|
1315
|
-
provide:
|
|
2082
|
+
provide: import_nestjs_agent_core3.AGENT_PRICING_STORE,
|
|
1316
2083
|
useClass: options.pricingStore
|
|
1317
2084
|
} : {
|
|
1318
|
-
provide:
|
|
2085
|
+
provide: import_nestjs_agent_core3.AGENT_PRICING_STORE,
|
|
1319
2086
|
useExisting: DrizzlePricingStore
|
|
1320
2087
|
},
|
|
1321
2088
|
{
|
|
1322
2089
|
provide: DrizzleGovernanceQueries,
|
|
1323
2090
|
useFactory: /* @__PURE__ */ __name((pricingStore) => new DrizzleGovernanceQueries(options.db, pricingStore), "useFactory"),
|
|
1324
2091
|
inject: [
|
|
1325
|
-
|
|
2092
|
+
import_nestjs_agent_core3.AGENT_PRICING_STORE
|
|
1326
2093
|
]
|
|
1327
2094
|
},
|
|
1328
2095
|
{
|
|
1329
|
-
provide:
|
|
2096
|
+
provide: import_nestjs_agent_core3.AGENT_GOVERNANCE_QUERIES,
|
|
1330
2097
|
useExisting: DrizzleGovernanceQueries
|
|
1331
2098
|
}
|
|
1332
2099
|
],
|
|
1333
2100
|
exports: [
|
|
2101
|
+
...options.ragIngestionLog === false ? [] : [
|
|
2102
|
+
DrizzleRagIngestionLog
|
|
2103
|
+
],
|
|
1334
2104
|
DrizzleAgentStore,
|
|
1335
|
-
|
|
2105
|
+
import_nestjs_agent_core3.AGENT_STORE,
|
|
2106
|
+
DrizzleMemoryProvider,
|
|
1336
2107
|
DrizzleGovernanceQueries,
|
|
1337
|
-
|
|
2108
|
+
import_nestjs_agent_core3.AGENT_GOVERNANCE_QUERIES,
|
|
1338
2109
|
DrizzlePricingStore,
|
|
1339
|
-
|
|
2110
|
+
import_nestjs_agent_core3.AGENT_PRICING_STORE
|
|
1340
2111
|
]
|
|
1341
2112
|
};
|
|
1342
2113
|
}
|
|
1343
2114
|
};
|
|
1344
|
-
DrizzleAgentStoreModule =
|
|
1345
|
-
(0,
|
|
2115
|
+
DrizzleAgentStoreModule = _ts_decorate2([
|
|
2116
|
+
(0, import_common2.Module)({})
|
|
1346
2117
|
], DrizzleAgentStoreModule);
|
|
1347
2118
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1348
2119
|
0 && (module.exports = {
|
|
1349
2120
|
DrizzleAgentStore,
|
|
1350
2121
|
DrizzleAgentStoreModule,
|
|
1351
2122
|
DrizzleGovernanceQueries,
|
|
2123
|
+
DrizzleMemoryProvider,
|
|
1352
2124
|
DrizzlePricingStore,
|
|
2125
|
+
DrizzleRagIngestionLog,
|
|
2126
|
+
RAG_INGESTION_LOG_PAGE_ORDER,
|
|
2127
|
+
agentMemory,
|
|
1353
2128
|
agentMessage,
|
|
1354
2129
|
agentModelPricing,
|
|
1355
2130
|
agentRun,
|
|
@@ -1357,6 +2132,7 @@ DrizzleAgentStoreModule = _ts_decorate([
|
|
|
1357
2132
|
agentThread,
|
|
1358
2133
|
agentTokenUsage,
|
|
1359
2134
|
agentToolCall,
|
|
1360
|
-
ensureAgentSchema
|
|
2135
|
+
ensureAgentSchema,
|
|
2136
|
+
ragIngestionLog
|
|
1361
2137
|
});
|
|
1362
2138
|
//# sourceMappingURL=index.cjs.map
|