@vellumai/assistant 0.8.12-dev.202606150824.4ddebe7 → 0.8.12-dev.202606151312.6aebfa4
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/openapi.yaml +55 -26
- package/package.json +1 -1
- package/src/memory/compaction-log-store-clickhouse.ts +6 -4
- package/src/memory/llm-request-log-source-clickhouse.ts +28 -0
- package/src/memory/llm-request-log-source-local.ts +11 -0
- package/src/memory/llm-request-log-source.ts +21 -4
- package/src/memory/llm-request-log-store.ts +39 -0
- package/src/runtime/routes/__tests__/conversation-compaction-routes.test.ts +190 -141
- package/src/runtime/routes/conversation-compaction-routes.ts +151 -121
package/openapi.yaml
CHANGED
|
@@ -8206,14 +8206,13 @@ paths:
|
|
|
8206
8206
|
/v1/conversations/{id}/compaction:
|
|
8207
8207
|
get:
|
|
8208
8208
|
operationId: conversations_by_id_compaction_get
|
|
8209
|
-
summary: Get the compaction
|
|
8209
|
+
summary: Get the compaction(s) attributed to an LLM call
|
|
8210
8210
|
description:
|
|
8211
|
-
Return the chronological list of
|
|
8212
|
-
|
|
8213
|
-
|
|
8214
|
-
|
|
8215
|
-
|
|
8216
|
-
strictly before the call's `createdAt` is in scope. Drives the Inspector's Compaction tab.
|
|
8211
|
+
Return the chronological list of compactions attributed to the call identified by `callId` — those that ran
|
|
8212
|
+
strictly between the previous real (non-`compactionAgent`) LLM call and the selected call. Served from the
|
|
8213
|
+
first-class compaction log when `compactionLogs.destination = "clickhouse"` is configured, falling back to the
|
|
8214
|
+
legacy projection over `llm_request_logs` rows where `call_site = "compactionAgent"`. Usually empty or a single
|
|
8215
|
+
compaction; the recovery cascade can fire several before one call lands. Drives the Inspector's Compaction tab.
|
|
8217
8216
|
tags:
|
|
8218
8217
|
- conversations
|
|
8219
8218
|
responses:
|
|
@@ -8235,54 +8234,84 @@ paths:
|
|
|
8235
8234
|
type: string
|
|
8236
8235
|
createdAt:
|
|
8237
8236
|
type: number
|
|
8238
|
-
|
|
8237
|
+
trigger:
|
|
8239
8238
|
anyOf:
|
|
8240
8239
|
- type: string
|
|
8241
8240
|
- type: "null"
|
|
8242
|
-
|
|
8241
|
+
compacted:
|
|
8242
|
+
anyOf:
|
|
8243
|
+
- type: boolean
|
|
8244
|
+
- type: "null"
|
|
8245
|
+
summaryFailed:
|
|
8246
|
+
anyOf:
|
|
8247
|
+
- type: boolean
|
|
8248
|
+
- type: "null"
|
|
8249
|
+
skipReason:
|
|
8243
8250
|
anyOf:
|
|
8244
8251
|
- type: string
|
|
8245
8252
|
- type: "null"
|
|
8246
|
-
|
|
8253
|
+
contextTokensBefore:
|
|
8247
8254
|
anyOf:
|
|
8248
8255
|
- type: number
|
|
8249
8256
|
- type: "null"
|
|
8250
|
-
|
|
8257
|
+
contextTokensAfter:
|
|
8251
8258
|
anyOf:
|
|
8252
8259
|
- type: number
|
|
8253
8260
|
- type: "null"
|
|
8254
|
-
|
|
8261
|
+
messagesBefore:
|
|
8255
8262
|
anyOf:
|
|
8256
8263
|
- type: number
|
|
8257
8264
|
- type: "null"
|
|
8258
|
-
|
|
8265
|
+
messagesAfter:
|
|
8259
8266
|
anyOf:
|
|
8260
|
-
- type:
|
|
8267
|
+
- type: number
|
|
8261
8268
|
- type: "null"
|
|
8262
|
-
|
|
8269
|
+
compactedMessages:
|
|
8263
8270
|
anyOf:
|
|
8264
8271
|
- type: number
|
|
8265
8272
|
- type: "null"
|
|
8266
|
-
|
|
8273
|
+
preservedTailMessages:
|
|
8274
|
+
anyOf:
|
|
8275
|
+
- type: number
|
|
8276
|
+
- type: "null"
|
|
8277
|
+
durationMs:
|
|
8278
|
+
anyOf:
|
|
8279
|
+
- type: number
|
|
8280
|
+
- type: "null"
|
|
8281
|
+
summaryModel:
|
|
8267
8282
|
anyOf:
|
|
8268
8283
|
- type: string
|
|
8269
8284
|
- type: "null"
|
|
8270
|
-
|
|
8285
|
+
summaryInputTokens:
|
|
8271
8286
|
anyOf:
|
|
8272
8287
|
- type: number
|
|
8273
8288
|
- type: "null"
|
|
8289
|
+
summaryOutputTokens:
|
|
8290
|
+
anyOf:
|
|
8291
|
+
- type: number
|
|
8292
|
+
- type: "null"
|
|
8293
|
+
summaryText:
|
|
8294
|
+
anyOf:
|
|
8295
|
+
- type: string
|
|
8296
|
+
- type: "null"
|
|
8274
8297
|
required:
|
|
8275
8298
|
- id
|
|
8276
8299
|
- createdAt
|
|
8277
|
-
-
|
|
8278
|
-
-
|
|
8279
|
-
-
|
|
8280
|
-
-
|
|
8300
|
+
- trigger
|
|
8301
|
+
- compacted
|
|
8302
|
+
- summaryFailed
|
|
8303
|
+
- skipReason
|
|
8304
|
+
- contextTokensBefore
|
|
8305
|
+
- contextTokensAfter
|
|
8306
|
+
- messagesBefore
|
|
8307
|
+
- messagesAfter
|
|
8308
|
+
- compactedMessages
|
|
8309
|
+
- preservedTailMessages
|
|
8281
8310
|
- durationMs
|
|
8282
|
-
-
|
|
8283
|
-
-
|
|
8284
|
-
-
|
|
8285
|
-
-
|
|
8311
|
+
- summaryModel
|
|
8312
|
+
- summaryInputTokens
|
|
8313
|
+
- summaryOutputTokens
|
|
8314
|
+
- summaryText
|
|
8286
8315
|
additionalProperties: false
|
|
8287
8316
|
required:
|
|
8288
8317
|
- conversationId
|
|
@@ -8303,7 +8332,7 @@ paths:
|
|
|
8303
8332
|
required: true
|
|
8304
8333
|
schema:
|
|
8305
8334
|
type: string
|
|
8306
|
-
description: ID of the selected LLM call from the rail. Defines the chronological cutoff for the
|
|
8335
|
+
description: ID of the selected LLM call from the rail. Defines the chronological cutoff for the attributed compactions.
|
|
8307
8336
|
/v1/conversations/{id}/inference-profile:
|
|
8308
8337
|
put:
|
|
8309
8338
|
operationId: conversations_by_id_inferenceprofile_put
|
package/package.json
CHANGED
|
@@ -213,10 +213,12 @@ export class ClickHouseCompactionLogStore {
|
|
|
213
213
|
|
|
214
214
|
/**
|
|
215
215
|
* Read all compaction attempts whose `started_at` falls strictly inside
|
|
216
|
-
* the
|
|
217
|
-
* the strict `>` / `<` predicate
|
|
218
|
-
* `getCompactionLogsBetween` on the llm-request-log sources
|
|
219
|
-
* route can
|
|
216
|
+
* the open window `(afterStartedAt, beforeStartedAt)`, pairing start/end
|
|
217
|
+
* rows by `compaction_id`. Mirrors the strict `>` / `<` predicate
|
|
218
|
+
* contract of `getCompactionLogsBetween` on the llm-request-log sources
|
|
219
|
+
* so the compaction route can scope both stores to the same call window
|
|
220
|
+
* (floor = previous real call's `createdAt`, ceiling = selected call's
|
|
221
|
+
* `createdAt`).
|
|
220
222
|
*/
|
|
221
223
|
async getEventsBetween(
|
|
222
224
|
conversationId: string,
|
|
@@ -256,6 +256,34 @@ export class ClickHouseLlmRequestLogSource implements LlmRequestLogSource {
|
|
|
256
256
|
return rows.map((r) => this.toLogRow(r));
|
|
257
257
|
}
|
|
258
258
|
|
|
259
|
+
async getPreviousNonCompactionCallCreatedAt(
|
|
260
|
+
conversationId: string,
|
|
261
|
+
beforeCreatedAt: number,
|
|
262
|
+
): Promise<number | null> {
|
|
263
|
+
const aid = await this.assistantId();
|
|
264
|
+
// `call_site != 'compactionAgent'` keeps the pre-migration-264 rows
|
|
265
|
+
// (stored as the empty-string default) in scope as real calls and
|
|
266
|
+
// excludes only the summarizer's own logs, matching the local
|
|
267
|
+
// store's `isNull(callSite) OR callSite != 'compactionAgent'`.
|
|
268
|
+
const sql = `SELECT
|
|
269
|
+
toUnixTimestamp64Milli(created_at) AS created_at
|
|
270
|
+
FROM ${this.tableRef()}
|
|
271
|
+
WHERE assistant_id = {assistant_id:String}
|
|
272
|
+
AND conversation_id = {conversation_id:String}
|
|
273
|
+
AND call_site != {call_site:String}
|
|
274
|
+
AND created_at < fromUnixTimestamp64Milli({before_created_at:Int64})
|
|
275
|
+
ORDER BY created_at DESC, id DESC
|
|
276
|
+
LIMIT 1
|
|
277
|
+
FORMAT JSONEachRow`;
|
|
278
|
+
const rows = await this.exec<{ created_at: string }>(sql, {
|
|
279
|
+
assistant_id: aid,
|
|
280
|
+
conversation_id: conversationId,
|
|
281
|
+
call_site: "compactionAgent",
|
|
282
|
+
before_created_at: String(beforeCreatedAt),
|
|
283
|
+
});
|
|
284
|
+
return rows[0] ? Number(rows[0].created_at) : null;
|
|
285
|
+
}
|
|
286
|
+
|
|
259
287
|
async getCompactionLogsBetween(
|
|
260
288
|
conversationId: string,
|
|
261
289
|
afterCreatedAt: number | null,
|
|
@@ -12,6 +12,7 @@ import type { LlmRequestLogSource } from "./llm-request-log-source.js";
|
|
|
12
12
|
import {
|
|
13
13
|
type CompactionAgentLogRow,
|
|
14
14
|
getCompactionLogsBetween,
|
|
15
|
+
getPreviousNonCompactionCallCreatedAt,
|
|
15
16
|
getRequestLogById,
|
|
16
17
|
getRequestLogMetaById,
|
|
17
18
|
getRequestLogsByConversationId,
|
|
@@ -39,6 +40,16 @@ export class LocalLlmRequestLogSource implements LlmRequestLogSource {
|
|
|
39
40
|
return getRequestLogsByConversationId(conversationId);
|
|
40
41
|
}
|
|
41
42
|
|
|
43
|
+
async getPreviousNonCompactionCallCreatedAt(
|
|
44
|
+
conversationId: string,
|
|
45
|
+
beforeCreatedAt: number,
|
|
46
|
+
): Promise<number | null> {
|
|
47
|
+
return getPreviousNonCompactionCallCreatedAt(
|
|
48
|
+
conversationId,
|
|
49
|
+
beforeCreatedAt,
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
42
53
|
async getCompactionLogsBetween(
|
|
43
54
|
conversationId: string,
|
|
44
55
|
afterCreatedAt: number | null,
|
|
@@ -51,15 +51,32 @@ export interface LlmRequestLogSource {
|
|
|
51
51
|
*/
|
|
52
52
|
getRequestLogsByConversationId(conversationId: string): Promise<LogRow[]>;
|
|
53
53
|
|
|
54
|
+
/**
|
|
55
|
+
* Return the `createdAt` of the most recent **non-`compactionAgent`**
|
|
56
|
+
* LLM call in the conversation that ran strictly before
|
|
57
|
+
* `beforeCreatedAt`, or `null` when the selected call is the first real
|
|
58
|
+
* call in the conversation.
|
|
59
|
+
*
|
|
60
|
+
* Drives the call-scoped floor for the Inspector's Compaction tab: a
|
|
61
|
+
* compaction is attributed to the next real call that ran after it, so
|
|
62
|
+
* the compactions for a given call are those that landed strictly
|
|
63
|
+
* between the previous real call and the selected call.
|
|
64
|
+
*/
|
|
65
|
+
getPreviousNonCompactionCallCreatedAt(
|
|
66
|
+
conversationId: string,
|
|
67
|
+
beforeCreatedAt: number,
|
|
68
|
+
): Promise<number | null>;
|
|
69
|
+
|
|
54
70
|
/**
|
|
55
71
|
* Fetch every `callSite = "compactionAgent"` log row in the conversation
|
|
56
72
|
* whose `createdAt` falls in the **open window**
|
|
57
73
|
* `(afterCreatedAt, beforeCreatedAt)`, ordered chronologically.
|
|
58
74
|
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
* `
|
|
62
|
-
*
|
|
75
|
+
* The legacy fallback for the Inspector's Compaction tab, used when the
|
|
76
|
+
* ClickHouse compaction log is unavailable. The route handler resolves
|
|
77
|
+
* the floor from `getPreviousNonCompactionCallCreatedAt` and the ceiling
|
|
78
|
+
* from the selected call's `createdAt`; this source method is
|
|
79
|
+
* bound-agnostic. See `getCompactionLogsBetween` in
|
|
63
80
|
* `llm-request-log-store.ts` for the SQL.
|
|
64
81
|
*/
|
|
65
82
|
getCompactionLogsBetween(
|
|
@@ -9,6 +9,8 @@ import {
|
|
|
9
9
|
isNull,
|
|
10
10
|
lt,
|
|
11
11
|
lte,
|
|
12
|
+
ne,
|
|
13
|
+
or,
|
|
12
14
|
sql,
|
|
13
15
|
} from "drizzle-orm";
|
|
14
16
|
import { v4 as uuid } from "uuid";
|
|
@@ -413,6 +415,43 @@ function selectUnlinkedLogsInRange(
|
|
|
413
415
|
.all();
|
|
414
416
|
}
|
|
415
417
|
|
|
418
|
+
/**
|
|
419
|
+
* Return the `createdAt` of the most recent **non-`compactionAgent`** LLM
|
|
420
|
+
* call in the conversation that ran strictly before `beforeCreatedAt`, or
|
|
421
|
+
* `null` when no such call exists (the selected call is the first real
|
|
422
|
+
* call in the conversation).
|
|
423
|
+
*
|
|
424
|
+
* Drives the call-scoped floor for the Inspector's Compaction tab. A
|
|
425
|
+
* compaction is attributed to the next real call that runs after it, so
|
|
426
|
+
* the trail for a given call is the set of compactions that landed
|
|
427
|
+
* strictly between the previous real call and the selected call. NULL
|
|
428
|
+
* `callSite` rows (pre-migration-264) are treated as real calls — only
|
|
429
|
+
* `compactionAgent` rows are excluded.
|
|
430
|
+
*/
|
|
431
|
+
export function getPreviousNonCompactionCallCreatedAt(
|
|
432
|
+
conversationId: string,
|
|
433
|
+
beforeCreatedAt: number,
|
|
434
|
+
): number | null {
|
|
435
|
+
const db = getDb();
|
|
436
|
+
const row = db
|
|
437
|
+
.select({ createdAt: llmRequestLogs.createdAt })
|
|
438
|
+
.from(llmRequestLogs)
|
|
439
|
+
.where(
|
|
440
|
+
and(
|
|
441
|
+
eq(llmRequestLogs.conversationId, conversationId),
|
|
442
|
+
lt(llmRequestLogs.createdAt, beforeCreatedAt),
|
|
443
|
+
or(
|
|
444
|
+
isNull(llmRequestLogs.callSite),
|
|
445
|
+
ne(llmRequestLogs.callSite, "compactionAgent"),
|
|
446
|
+
),
|
|
447
|
+
),
|
|
448
|
+
)
|
|
449
|
+
.orderBy(desc(llmRequestLogs.createdAt), desc(llmRequestLogs.id))
|
|
450
|
+
.limit(1)
|
|
451
|
+
.get();
|
|
452
|
+
return row?.createdAt ?? null;
|
|
453
|
+
}
|
|
454
|
+
|
|
416
455
|
/**
|
|
417
456
|
* Fetch every `compactionAgent` log row in the conversation whose
|
|
418
457
|
* `createdAt` falls in the **open window** `(afterCreatedAt, beforeCreatedAt)`,
|