@sentry/junior 0.112.0 → 0.114.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/{agent-hooks-6MVTPKP4.js → agent-hooks-WNBUY4OB.js} +8 -8
- package/dist/api/conversations/cursor.d.ts +17 -0
- package/dist/api/conversations/detail.d.ts +40 -18
- package/dist/api/conversations/event-list.d.ts +115 -0
- package/dist/api/conversations/event-page.d.ts +18 -0
- package/dist/api/conversations/events.d.ts +6 -2
- package/dist/api/conversations/projection.d.ts +6 -1
- package/dist/api/schema/conversation.d.ts +228 -51
- package/dist/api/schema.d.ts +2 -2
- package/dist/api/schema.js +7 -1
- package/dist/api.js +461 -139
- package/dist/app.d.ts +2 -0
- package/dist/app.js +33 -24
- package/dist/{catalog-runtime-UEO25P2J.js → catalog-runtime-6O4M6JGA.js} +5 -5
- package/dist/chat/config.d.ts +1 -1
- package/dist/chat/conversations/history.d.ts +86 -0
- package/dist/chat/conversations/projection.d.ts +20 -1
- package/dist/chat/pi/transcript.d.ts +2 -0
- package/dist/chat/services/context-budget.d.ts +7 -2
- package/dist/chat/services/context-compaction.d.ts +28 -1
- package/dist/chat/services/conversation-memory.d.ts +1 -0
- package/dist/chat/services/provider-error.d.ts +40 -0
- package/dist/chat/services/provider-retry.d.ts +3 -6
- package/dist/chat/services/turn-router.d.ts +1 -0
- package/dist/chat/task-execution/state.d.ts +2 -2
- package/dist/chat/task-execution/store.d.ts +1 -1
- package/dist/chat/tools/sandbox/edit-file.d.ts +1 -1
- package/dist/chat/tools/sandbox/text-edits.d.ts +1 -0
- package/dist/{chunk-CSS7JHEM.js → chunk-4FUEG3QY.js} +1 -1
- package/dist/{chunk-AU2JVUDF.js → chunk-5CZ7RETL.js} +1 -1
- package/dist/{chunk-SKEMI4IF.js → chunk-6QWPVTMO.js} +200 -52
- package/dist/{chunk-AWNDKI5K.js → chunk-ABPSDO6M.js} +20 -15
- package/dist/{chunk-QIALGHRN.js → chunk-FIGAF6KL.js} +34 -2
- package/dist/{chunk-TZU3R5OC.js → chunk-K2W4CK7K.js} +1 -1
- package/dist/{chunk-2FJ6WEYV.js → chunk-O4GT7LYB.js} +1 -1
- package/dist/{chunk-ZHP4KNF7.js → chunk-OSKEC4XU.js} +1 -1
- package/dist/{chunk-IV2O4HQJ.js → chunk-PM3PX42K.js} +1 -1
- package/dist/{chunk-NDQL4ESR.js → chunk-RD7EJI7H.js} +2 -2
- package/dist/{chunk-JE23YR3X.js → chunk-S4QDH23A.js} +75 -43
- package/dist/{chunk-GJG67YFS.js → chunk-TLGM5X2M.js} +2 -2
- package/dist/{chunk-VBSVNOLA.js → chunk-VNNBSKCO.js} +5 -5
- package/dist/{chunk-4EJO4HIC.js → chunk-W6RDUAO3.js} +1 -1
- package/dist/{chunk-GR4IB6OQ.js → chunk-WV4UJBAS.js} +431 -96
- package/dist/{chunk-66IP6WED.js → chunk-XLFBQJUO.js} +4 -4
- package/dist/{chunk-X3SP5RDW.js → chunk-YU6PO42Q.js} +1 -1
- package/dist/{chunk-PK4ETCUQ.js → chunk-ZGXH3REA.js} +226 -215
- package/dist/cli/chat.js +19 -19
- package/dist/cli/check.js +6 -6
- package/dist/cli/plugins.js +11 -11
- package/dist/cli/snapshot-warmup.js +8 -8
- package/dist/cli/upgrade.js +5 -5
- package/dist/{db-P5H5RVQV.js → db-4VLP7KBF.js} +5 -5
- package/dist/instrumentation.js +2 -2
- package/dist/nitro.js +2 -2
- package/dist/{runner-B4ZDUO3R.js → runner-IPXLWQOF.js} +12 -13
- package/dist/{skills-GWTOZ3XV.js → skills-QCNZISNF.js} +6 -6
- package/dist/{validation-QFIC6XH6.js → validation-I2BW3UHD.js} +6 -6
- package/dist/version.js +1 -1
- package/package.json +6 -6
package/dist/api.js
CHANGED
|
@@ -5,7 +5,10 @@ import {
|
|
|
5
5
|
apiErrorSchema,
|
|
6
6
|
archiveConversationBodySchema,
|
|
7
7
|
archiveConversationResponseSchema,
|
|
8
|
+
conversationDetailQuerySchema,
|
|
8
9
|
conversationDetailReportSchema,
|
|
10
|
+
conversationEventPageSchema,
|
|
11
|
+
conversationEventsQuerySchema,
|
|
9
12
|
conversationFeedQuerySchema,
|
|
10
13
|
conversationFeedSchema,
|
|
11
14
|
conversationParamsSchema,
|
|
@@ -15,13 +18,13 @@ import {
|
|
|
15
18
|
locationDirectoryReportSchema,
|
|
16
19
|
locationParamsSchema,
|
|
17
20
|
personParamsSchema
|
|
18
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-S4QDH23A.js";
|
|
19
22
|
import {
|
|
20
23
|
buildSentryConversationUrl,
|
|
21
24
|
formatSlackConversationRedactedLabel,
|
|
22
25
|
readHealthReport,
|
|
23
26
|
resolveSlackConversationContextFromThreadId
|
|
24
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-O4GT7LYB.js";
|
|
25
28
|
import {
|
|
26
29
|
healthReportSchema,
|
|
27
30
|
pluginOperationalReportFeedSchema,
|
|
@@ -34,12 +37,12 @@ import {
|
|
|
34
37
|
hasAgentTurnUsage
|
|
35
38
|
} from "./chunk-MU6HHZEN.js";
|
|
36
39
|
import "./chunk-PDO5BLNM.js";
|
|
37
|
-
import "./chunk-
|
|
40
|
+
import "./chunk-RD7EJI7H.js";
|
|
38
41
|
import {
|
|
39
42
|
decodeStoredConversationEvent,
|
|
40
43
|
getDb,
|
|
41
44
|
getSqlExecutor
|
|
42
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-FIGAF6KL.js";
|
|
43
46
|
import {
|
|
44
47
|
juniorConversationEvents,
|
|
45
48
|
juniorConversations,
|
|
@@ -47,7 +50,7 @@ import {
|
|
|
47
50
|
juniorUsers
|
|
48
51
|
} from "./chunk-JQFJO5WH.js";
|
|
49
52
|
import "./chunk-4ZNGQH7C.js";
|
|
50
|
-
import "./chunk-
|
|
53
|
+
import "./chunk-ZGXH3REA.js";
|
|
51
54
|
import {
|
|
52
55
|
juniorDestinations
|
|
53
56
|
} from "./chunk-VFUK3X5B.js";
|
|
@@ -55,11 +58,11 @@ import {
|
|
|
55
58
|
canExposeConversationPayload,
|
|
56
59
|
parseSlackThreadId
|
|
57
60
|
} from "./chunk-6Y5L4BOM.js";
|
|
58
|
-
import "./chunk-
|
|
61
|
+
import "./chunk-4FUEG3QY.js";
|
|
59
62
|
import "./chunk-42WRQLJ6.js";
|
|
60
63
|
import "./chunk-6GWA276C.js";
|
|
61
|
-
import "./chunk-
|
|
62
|
-
import "./chunk-
|
|
64
|
+
import "./chunk-5CZ7RETL.js";
|
|
65
|
+
import "./chunk-PM3PX42K.js";
|
|
63
66
|
import "./chunk-MLKGABMK.js";
|
|
64
67
|
|
|
65
68
|
// src/api.ts
|
|
@@ -156,9 +159,6 @@ var archive_default = defineApiRoute({
|
|
|
156
159
|
}
|
|
157
160
|
});
|
|
158
161
|
|
|
159
|
-
// src/api/conversations/detail.ts
|
|
160
|
-
import { and as and5, asc as asc2, eq as eq6, getTableColumns, inArray as inArray3, sql as sql3 } from "drizzle-orm";
|
|
161
|
-
|
|
162
162
|
// src/chat/pi/sql-model-usage.ts
|
|
163
163
|
import { and as and2, eq as eq2, sql } from "drizzle-orm";
|
|
164
164
|
var message = sql`${juniorConversationEvents.payload}->'message'`;
|
|
@@ -275,14 +275,74 @@ async function readConversationModelUsageFromSql(executor, options) {
|
|
|
275
275
|
});
|
|
276
276
|
}
|
|
277
277
|
|
|
278
|
-
// src/api/conversations/
|
|
278
|
+
// src/api/conversations/cursor.ts
|
|
279
|
+
import { createHmac, timingSafeEqual } from "crypto";
|
|
279
280
|
import { z } from "zod";
|
|
281
|
+
var CURSOR_CONTEXT = "junior-conversation-report-cursor";
|
|
282
|
+
var conversationCursorPayloadSchema = z.object({
|
|
283
|
+
conversationId: z.string().min(1),
|
|
284
|
+
seq: z.number().int().min(-1),
|
|
285
|
+
version: z.literal(1)
|
|
286
|
+
}).strict();
|
|
287
|
+
function cursorSecret() {
|
|
288
|
+
const secret = process.env.JUNIOR_SECRET?.trim();
|
|
289
|
+
if (!secret) {
|
|
290
|
+
throw new Error("Cannot sign conversation cursor without JUNIOR_SECRET");
|
|
291
|
+
}
|
|
292
|
+
return secret;
|
|
293
|
+
}
|
|
294
|
+
function signature(payload) {
|
|
295
|
+
return createHmac("sha256", cursorSecret()).update(`${CURSOR_CONTEXT}:${payload}`).digest("base64url");
|
|
296
|
+
}
|
|
297
|
+
function encodeConversationCursor(payload) {
|
|
298
|
+
const encoded = Buffer.from(
|
|
299
|
+
JSON.stringify({ ...payload, version: 1 }),
|
|
300
|
+
"utf8"
|
|
301
|
+
).toString("base64url");
|
|
302
|
+
return `${encoded}.${signature(encoded)}`;
|
|
303
|
+
}
|
|
304
|
+
function decodeConversationCursor(args) {
|
|
305
|
+
const [encoded, actualSignature, extra] = args.cursor.split(".");
|
|
306
|
+
if (!encoded || !actualSignature || extra !== void 0) return void 0;
|
|
307
|
+
const expected = Buffer.from(signature(encoded));
|
|
308
|
+
const actual = Buffer.from(actualSignature);
|
|
309
|
+
if (expected.length !== actual.length || !timingSafeEqual(expected, actual)) {
|
|
310
|
+
return void 0;
|
|
311
|
+
}
|
|
312
|
+
try {
|
|
313
|
+
const parsed = conversationCursorPayloadSchema.parse(
|
|
314
|
+
JSON.parse(Buffer.from(encoded, "base64url").toString("utf8"))
|
|
315
|
+
);
|
|
316
|
+
if (parsed.conversationId !== args.conversationId) {
|
|
317
|
+
return void 0;
|
|
318
|
+
}
|
|
319
|
+
return { seq: parsed.seq };
|
|
320
|
+
} catch {
|
|
321
|
+
return void 0;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// src/api/conversations/event-page.ts
|
|
326
|
+
import {
|
|
327
|
+
and as and3,
|
|
328
|
+
asc,
|
|
329
|
+
desc,
|
|
330
|
+
eq as eq3,
|
|
331
|
+
getTableColumns,
|
|
332
|
+
inArray,
|
|
333
|
+
lt,
|
|
334
|
+
sql as sql2
|
|
335
|
+
} from "drizzle-orm";
|
|
336
|
+
|
|
337
|
+
// src/api/conversations/events.ts
|
|
338
|
+
import { z as z2 } from "zod";
|
|
280
339
|
var conversationReportSourceEventTypes = [
|
|
281
340
|
"message",
|
|
282
341
|
"message_handled",
|
|
283
342
|
"agent_step",
|
|
284
343
|
"tool_execution_started",
|
|
285
344
|
"turn_started",
|
|
345
|
+
"turn_routed",
|
|
286
346
|
"turn_completed",
|
|
287
347
|
"turn_failed",
|
|
288
348
|
"compaction",
|
|
@@ -290,31 +350,33 @@ var conversationReportSourceEventTypes = [
|
|
|
290
350
|
"subagent_started",
|
|
291
351
|
"subagent_ended"
|
|
292
352
|
];
|
|
293
|
-
var reportingAssistantMessageSchema =
|
|
294
|
-
role:
|
|
295
|
-
content:
|
|
353
|
+
var reportingAssistantMessageSchema = z2.object({
|
|
354
|
+
role: z2.literal("assistant"),
|
|
355
|
+
content: z2.array(z2.unknown())
|
|
296
356
|
}).passthrough();
|
|
297
|
-
var reportingToolCallPartSchema =
|
|
298
|
-
type:
|
|
299
|
-
id:
|
|
300
|
-
name:
|
|
301
|
-
arguments:
|
|
357
|
+
var reportingToolCallPartSchema = z2.object({
|
|
358
|
+
type: z2.literal("toolCall"),
|
|
359
|
+
id: z2.string().min(1),
|
|
360
|
+
name: z2.string().min(1),
|
|
361
|
+
arguments: z2.unknown()
|
|
302
362
|
}).passthrough();
|
|
303
|
-
var reportingToolResultMessageSchema =
|
|
304
|
-
role:
|
|
305
|
-
toolCallId:
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
363
|
+
var reportingToolResultMessageSchema = z2.object({
|
|
364
|
+
role: z2.literal("toolResult"),
|
|
365
|
+
toolCallId: z2.string().min(1),
|
|
366
|
+
toolName: z2.string().min(1).optional(),
|
|
367
|
+
name: z2.string().min(1).optional(),
|
|
368
|
+
content: z2.array(z2.unknown()),
|
|
369
|
+
details: z2.unknown().optional(),
|
|
370
|
+
isError: z2.boolean().optional()
|
|
309
371
|
}).passthrough();
|
|
310
|
-
var reportingToolResultDetailsSchema =
|
|
311
|
-
ok:
|
|
312
|
-
status:
|
|
372
|
+
var reportingToolResultDetailsSchema = z2.object({
|
|
373
|
+
ok: z2.boolean().optional(),
|
|
374
|
+
status: z2.string().optional()
|
|
313
375
|
}).passthrough();
|
|
314
|
-
var reportingTextPartSchema =
|
|
315
|
-
var reportingMediaPartSchema =
|
|
316
|
-
type:
|
|
317
|
-
mimeType:
|
|
376
|
+
var reportingTextPartSchema = z2.object({ type: z2.literal("text"), text: z2.string() }).passthrough();
|
|
377
|
+
var reportingMediaPartSchema = z2.object({
|
|
378
|
+
type: z2.enum(["image", "audio"]),
|
|
379
|
+
mimeType: z2.string().min(1).optional()
|
|
318
380
|
}).passthrough();
|
|
319
381
|
function sanitizeModelContentPart(value) {
|
|
320
382
|
const text = reportingTextPartSchema.safeParse(value);
|
|
@@ -343,6 +405,9 @@ function reportToolCalls(args) {
|
|
|
343
405
|
{
|
|
344
406
|
toolCallId: call.data.id,
|
|
345
407
|
name: call.data.name,
|
|
408
|
+
status: "running",
|
|
409
|
+
startedAt: new Date(args.createdAtMs).toISOString(),
|
|
410
|
+
startedSeq: args.seq,
|
|
346
411
|
...args.canExposePayload && call.data.arguments !== void 0 ? { input: call.data.arguments } : {}
|
|
347
412
|
}
|
|
348
413
|
];
|
|
@@ -357,13 +422,37 @@ function reportToolResult(args) {
|
|
|
357
422
|
);
|
|
358
423
|
const outcome = message2.data.isError === true || details.success && (details.data.ok === false || details.data.status === "error") ? "error" : "completed";
|
|
359
424
|
const output = modelVisibleToolOutput(message2.data.content);
|
|
425
|
+
const name = message2.data.toolName ?? message2.data.name ?? args.start?.name;
|
|
426
|
+
if (!name) return void 0;
|
|
360
427
|
return {
|
|
361
|
-
type: "
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
428
|
+
type: "tool_calls",
|
|
429
|
+
calls: [
|
|
430
|
+
{
|
|
431
|
+
toolCallId: message2.data.toolCallId,
|
|
432
|
+
name,
|
|
433
|
+
status: outcome,
|
|
434
|
+
...args.start ? {
|
|
435
|
+
startedAt: new Date(args.start.createdAtMs).toISOString(),
|
|
436
|
+
startedSeq: args.start.seq
|
|
437
|
+
} : {},
|
|
438
|
+
...args.canExposePayload && output !== void 0 ? { output } : {}
|
|
439
|
+
}
|
|
440
|
+
]
|
|
365
441
|
};
|
|
366
442
|
}
|
|
443
|
+
function conversationReportToolResultIds(events) {
|
|
444
|
+
return [
|
|
445
|
+
...new Set(
|
|
446
|
+
events.flatMap((event) => {
|
|
447
|
+
if (event.data.type !== "agent_step") return [];
|
|
448
|
+
const result = reportingToolResultMessageSchema.safeParse(
|
|
449
|
+
event.data.message
|
|
450
|
+
);
|
|
451
|
+
return result.success ? [result.data.toolCallId] : [];
|
|
452
|
+
})
|
|
453
|
+
)
|
|
454
|
+
];
|
|
455
|
+
}
|
|
367
456
|
function reportEventData(args) {
|
|
368
457
|
const { data } = args;
|
|
369
458
|
switch (data.type) {
|
|
@@ -386,6 +475,16 @@ function reportEventData(args) {
|
|
|
386
475
|
turnId: data.turnId,
|
|
387
476
|
state: "started"
|
|
388
477
|
};
|
|
478
|
+
case "turn_routed":
|
|
479
|
+
return {
|
|
480
|
+
type: "turn_routed",
|
|
481
|
+
turnId: data.turnId,
|
|
482
|
+
modelProfile: data.modelProfile,
|
|
483
|
+
modelId: data.modelId,
|
|
484
|
+
reasoningLevel: data.reasoningLevel,
|
|
485
|
+
...data.confidence !== void 0 ? { confidence: data.confidence } : {},
|
|
486
|
+
source: data.source
|
|
487
|
+
};
|
|
389
488
|
case "turn_completed":
|
|
390
489
|
return {
|
|
391
490
|
type: "turn_lifecycle",
|
|
@@ -400,44 +499,105 @@ function reportEventData(args) {
|
|
|
400
499
|
failureKind: data.failureCode === "delivery_failed" ? "delivery" : "agent"
|
|
401
500
|
};
|
|
402
501
|
case "compaction":
|
|
403
|
-
return {
|
|
502
|
+
return {
|
|
503
|
+
type: "compaction",
|
|
504
|
+
modelProfile: data.modelProfile,
|
|
505
|
+
modelId: data.modelId,
|
|
506
|
+
...data.details ? { details: data.details } : {}
|
|
507
|
+
};
|
|
404
508
|
default:
|
|
405
509
|
return void 0;
|
|
406
510
|
}
|
|
407
511
|
}
|
|
408
|
-
function
|
|
512
|
+
function projectConversationReportEventPage(args) {
|
|
409
513
|
const subagentStarts = /* @__PURE__ */ new Map();
|
|
514
|
+
for (const event of args.subagentStartEvents ?? []) {
|
|
515
|
+
if (event.data.type === "subagent_started") {
|
|
516
|
+
subagentStarts.set(event.data.subagentInvocationId, {
|
|
517
|
+
createdAtMs: event.createdAtMs,
|
|
518
|
+
data: event.data,
|
|
519
|
+
seq: event.seq
|
|
520
|
+
});
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
const toolStarts = /* @__PURE__ */ new Map();
|
|
524
|
+
for (const event of args.toolStartEvents ?? []) {
|
|
525
|
+
if (event.data.type === "tool_execution_started") {
|
|
526
|
+
const current = toolStarts.get(event.data.toolCallId);
|
|
527
|
+
if (!current || event.seq < current.seq) {
|
|
528
|
+
toolStarts.set(event.data.toolCallId, {
|
|
529
|
+
createdAtMs: event.createdAtMs,
|
|
530
|
+
name: event.data.toolName,
|
|
531
|
+
seq: event.seq
|
|
532
|
+
});
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
}
|
|
410
536
|
const projected = [];
|
|
411
537
|
for (const event of args.events) {
|
|
412
538
|
let data;
|
|
413
539
|
if (event.data.type === "agent_step") {
|
|
414
540
|
const reportArgs = {
|
|
415
541
|
canExposePayload: args.canExposePayload,
|
|
416
|
-
|
|
542
|
+
createdAtMs: event.createdAtMs,
|
|
543
|
+
message: event.data.message,
|
|
544
|
+
seq: event.seq
|
|
417
545
|
};
|
|
418
|
-
|
|
546
|
+
const result = reportingToolResultMessageSchema.safeParse(
|
|
547
|
+
event.data.message
|
|
548
|
+
);
|
|
549
|
+
const start = result.success ? toolStarts.get(result.data.toolCallId) : void 0;
|
|
550
|
+
data = reportToolCalls(reportArgs) ?? reportToolResult({
|
|
551
|
+
canExposePayload: args.canExposePayload,
|
|
552
|
+
message: event.data.message,
|
|
553
|
+
...start && start.seq < event.seq ? { start } : {}
|
|
554
|
+
});
|
|
419
555
|
} else if (event.data.type === "tool_execution_started") {
|
|
556
|
+
toolStarts.set(event.data.toolCallId, {
|
|
557
|
+
createdAtMs: event.createdAtMs,
|
|
558
|
+
name: event.data.toolName,
|
|
559
|
+
seq: event.seq
|
|
560
|
+
});
|
|
420
561
|
data = {
|
|
421
|
-
type: "
|
|
422
|
-
|
|
423
|
-
|
|
562
|
+
type: "tool_calls",
|
|
563
|
+
calls: [
|
|
564
|
+
{
|
|
565
|
+
toolCallId: event.data.toolCallId,
|
|
566
|
+
name: event.data.toolName,
|
|
567
|
+
status: "running",
|
|
568
|
+
startedAt: new Date(event.createdAtMs).toISOString(),
|
|
569
|
+
startedSeq: event.seq
|
|
570
|
+
}
|
|
571
|
+
]
|
|
424
572
|
};
|
|
425
573
|
} else if (event.data.type === "subagent_started") {
|
|
426
|
-
subagentStarts.set(event.data.subagentInvocationId,
|
|
574
|
+
subagentStarts.set(event.data.subagentInvocationId, {
|
|
575
|
+
createdAtMs: event.createdAtMs,
|
|
576
|
+
data: event.data,
|
|
577
|
+
seq: event.seq
|
|
578
|
+
});
|
|
427
579
|
data = {
|
|
428
|
-
type: "
|
|
580
|
+
type: "subagent",
|
|
581
|
+
startedSeq: event.seq,
|
|
582
|
+
startedAt: new Date(event.createdAtMs).toISOString(),
|
|
429
583
|
childConversationId: event.data.childConversationId,
|
|
430
584
|
subagentKind: event.data.subagentKind,
|
|
585
|
+
status: "running",
|
|
431
586
|
...event.data.parentToolCallId ? { parentToolCallId: event.data.parentToolCallId } : {}
|
|
432
587
|
};
|
|
433
588
|
} else if (event.data.type === "subagent_ended") {
|
|
434
|
-
const
|
|
435
|
-
if (
|
|
589
|
+
const started = subagentStarts.get(event.data.subagentInvocationId);
|
|
590
|
+
if (started && started.seq < event.seq) {
|
|
436
591
|
data = {
|
|
437
|
-
type: "
|
|
438
|
-
startedSeq,
|
|
439
|
-
|
|
592
|
+
type: "subagent",
|
|
593
|
+
startedSeq: started.seq,
|
|
594
|
+
startedAt: new Date(started.createdAtMs).toISOString(),
|
|
595
|
+
childConversationId: started.data.childConversationId,
|
|
596
|
+
subagentKind: started.data.subagentKind,
|
|
597
|
+
...started.data.parentToolCallId ? { parentToolCallId: started.data.parentToolCallId } : {},
|
|
598
|
+
status: event.data.outcome === "success" ? "completed" : event.data.outcome
|
|
440
599
|
};
|
|
600
|
+
subagentStarts.delete(event.data.subagentInvocationId);
|
|
441
601
|
}
|
|
442
602
|
} else if (event.data.type === "handoff") {
|
|
443
603
|
data = {
|
|
@@ -465,8 +625,116 @@ function projectConversationReportEvents(args) {
|
|
|
465
625
|
return projected;
|
|
466
626
|
}
|
|
467
627
|
|
|
628
|
+
// src/api/conversations/event-page.ts
|
|
629
|
+
var conversationEventColumns = getTableColumns(juniorConversationEvents);
|
|
630
|
+
var MIN_SCAN_SIZE = 64;
|
|
631
|
+
async function readConversationEventRows(executor, args) {
|
|
632
|
+
return executor.db().select({
|
|
633
|
+
...conversationEventColumns,
|
|
634
|
+
// Replacement history is model context, never dashboard report data.
|
|
635
|
+
payload: sql2`case
|
|
636
|
+
when ${juniorConversationEvents.type} in ('compaction', 'handoff')
|
|
637
|
+
then jsonb_set(
|
|
638
|
+
${juniorConversationEvents.payload},
|
|
639
|
+
'{replacementHistory}',
|
|
640
|
+
'[]'::jsonb
|
|
641
|
+
)
|
|
642
|
+
else ${juniorConversationEvents.payload}
|
|
643
|
+
end`
|
|
644
|
+
}).from(juniorConversationEvents).where(
|
|
645
|
+
and3(
|
|
646
|
+
eq3(juniorConversationEvents.conversationId, args.conversationId),
|
|
647
|
+
args.beforeSeq === void 0 ? void 0 : lt(juniorConversationEvents.seq, args.beforeSeq),
|
|
648
|
+
inArray(
|
|
649
|
+
juniorConversationEvents.type,
|
|
650
|
+
args.types ?? [...conversationReportSourceEventTypes]
|
|
651
|
+
),
|
|
652
|
+
args.subagentInvocationIds === void 0 ? void 0 : inArray(
|
|
653
|
+
sql2`${juniorConversationEvents.payload}->>'subagentInvocationId'`,
|
|
654
|
+
args.subagentInvocationIds
|
|
655
|
+
),
|
|
656
|
+
args.toolCallIds === void 0 ? void 0 : inArray(
|
|
657
|
+
sql2`${juniorConversationEvents.payload}->>'toolCallId'`,
|
|
658
|
+
args.toolCallIds
|
|
659
|
+
)
|
|
660
|
+
)
|
|
661
|
+
).orderBy(
|
|
662
|
+
args.direction === "forward" ? asc(juniorConversationEvents.seq) : desc(juniorConversationEvents.seq)
|
|
663
|
+
).limit(args.limit);
|
|
664
|
+
}
|
|
665
|
+
function decodeConversationEventRow(row) {
|
|
666
|
+
return decodeStoredConversationEvent({
|
|
667
|
+
schemaVersion: row.schemaVersion,
|
|
668
|
+
seq: row.seq,
|
|
669
|
+
historyVersion: row.historyVersion,
|
|
670
|
+
...row.idempotencyKey ? { idempotencyKey: row.idempotencyKey } : {},
|
|
671
|
+
createdAtMs: row.createdAt.getTime(),
|
|
672
|
+
type: row.type,
|
|
673
|
+
payload: row.payload
|
|
674
|
+
});
|
|
675
|
+
}
|
|
676
|
+
async function projectConversationEventRows(executor, args) {
|
|
677
|
+
const events = args.rows.map(decodeConversationEventRow).sort((left, right) => left.seq - right.seq);
|
|
678
|
+
const endedInvocationIds = [
|
|
679
|
+
...new Set(
|
|
680
|
+
events.flatMap(
|
|
681
|
+
(event) => event.data.type === "subagent_ended" ? [event.data.subagentInvocationId] : []
|
|
682
|
+
)
|
|
683
|
+
)
|
|
684
|
+
];
|
|
685
|
+
const subagentStartRows = endedInvocationIds.length === 0 ? [] : await readConversationEventRows(executor, {
|
|
686
|
+
conversationId: args.conversationId,
|
|
687
|
+
direction: "forward",
|
|
688
|
+
limit: endedInvocationIds.length,
|
|
689
|
+
subagentInvocationIds: endedInvocationIds,
|
|
690
|
+
types: ["subagent_started"]
|
|
691
|
+
});
|
|
692
|
+
const toolResultIds = conversationReportToolResultIds(events);
|
|
693
|
+
const toolStartRows = toolResultIds.length === 0 ? [] : await readConversationEventRows(executor, {
|
|
694
|
+
conversationId: args.conversationId,
|
|
695
|
+
direction: "forward",
|
|
696
|
+
limit: toolResultIds.length,
|
|
697
|
+
toolCallIds: toolResultIds,
|
|
698
|
+
types: ["tool_execution_started"]
|
|
699
|
+
});
|
|
700
|
+
return projectConversationReportEventPage({
|
|
701
|
+
canExposePayload: args.canExposePayload,
|
|
702
|
+
events,
|
|
703
|
+
subagentStartEvents: subagentStartRows.map(decodeConversationEventRow),
|
|
704
|
+
toolStartEvents: toolStartRows.map(decodeConversationEventRow)
|
|
705
|
+
});
|
|
706
|
+
}
|
|
707
|
+
async function readConversationEventPage(executor, args) {
|
|
708
|
+
const scanSize = Math.max(args.limit + 1, MIN_SCAN_SIZE);
|
|
709
|
+
const rows = [];
|
|
710
|
+
let beforeSeq = args.beforeSeq;
|
|
711
|
+
let projected = [];
|
|
712
|
+
while (projected.length <= args.limit) {
|
|
713
|
+
const batch = await readConversationEventRows(executor, {
|
|
714
|
+
beforeSeq,
|
|
715
|
+
conversationId: args.conversationId,
|
|
716
|
+
direction: "backward",
|
|
717
|
+
limit: scanSize
|
|
718
|
+
});
|
|
719
|
+
if (batch.length === 0) break;
|
|
720
|
+
rows.push(...batch);
|
|
721
|
+
projected = await projectConversationEventRows(executor, {
|
|
722
|
+
canExposePayload: args.canExposePayload,
|
|
723
|
+
conversationId: args.conversationId,
|
|
724
|
+
rows
|
|
725
|
+
});
|
|
726
|
+
if (projected.length > args.limit || batch.length < scanSize) break;
|
|
727
|
+
beforeSeq = batch.at(-1).seq;
|
|
728
|
+
}
|
|
729
|
+
const events = projected.slice(-args.limit);
|
|
730
|
+
return {
|
|
731
|
+
events,
|
|
732
|
+
...projected.length > events.length && events[0] ? { previousSeq: events[0].seq } : {}
|
|
733
|
+
};
|
|
734
|
+
}
|
|
735
|
+
|
|
468
736
|
// src/api/conversations/list.ts
|
|
469
|
-
import { and as
|
|
737
|
+
import { and as and5, asc as asc2, desc as desc2, eq as eq6, isNull as isNull2 } from "drizzle-orm";
|
|
470
738
|
|
|
471
739
|
// src/api/conversations/shared.ts
|
|
472
740
|
function slackStatsLocationLabel(input) {
|
|
@@ -566,6 +834,15 @@ function channelNameRedactedFromConversation(conversation, canViewPrivateContent
|
|
|
566
834
|
}
|
|
567
835
|
return !canViewPrivateContent;
|
|
568
836
|
}
|
|
837
|
+
function conversationEventHistory(args) {
|
|
838
|
+
if (args.transcriptPurgedAtMs !== void 0) {
|
|
839
|
+
return {
|
|
840
|
+
status: "expired",
|
|
841
|
+
expiredAt: new Date(args.transcriptPurgedAtMs).toISOString()
|
|
842
|
+
};
|
|
843
|
+
}
|
|
844
|
+
return args.canExposePayload ? { status: "available" } : { status: "redacted", reason: "non_public_conversation" };
|
|
845
|
+
}
|
|
569
846
|
function conversationSummaryFromStoredConversation(args) {
|
|
570
847
|
const { conversation, durationMs, usage: usage3 } = args;
|
|
571
848
|
const canViewPrivateContent = args.access?.canViewPrivateContent ?? false;
|
|
@@ -610,7 +887,7 @@ function conversationSummaryFromStoredConversation(args) {
|
|
|
610
887
|
}
|
|
611
888
|
|
|
612
889
|
// src/api/conversations/access.ts
|
|
613
|
-
import { eq as
|
|
890
|
+
import { eq as eq4, inArray as inArray2 } from "drizzle-orm";
|
|
614
891
|
import { alias } from "drizzle-orm/pg-core";
|
|
615
892
|
var rootConversation = alias(juniorConversations, "access_root_conversation");
|
|
616
893
|
var rootDestination = alias(juniorDestinations, "access_root_destination");
|
|
@@ -630,17 +907,17 @@ async function readConversationAccessFromSql(db, conversationIds, verifiedViewer
|
|
|
630
907
|
rootEmailVerified: rootIdentity.emailVerified
|
|
631
908
|
}).from(juniorConversations).leftJoin(
|
|
632
909
|
rootConversation,
|
|
633
|
-
|
|
910
|
+
eq4(
|
|
634
911
|
rootConversation.conversationId,
|
|
635
912
|
juniorConversations.rootConversationId
|
|
636
913
|
)
|
|
637
914
|
).leftJoin(
|
|
638
915
|
rootDestination,
|
|
639
|
-
|
|
916
|
+
eq4(rootDestination.id, rootConversation.destinationId)
|
|
640
917
|
).leftJoin(
|
|
641
918
|
rootIdentity,
|
|
642
|
-
|
|
643
|
-
).where(
|
|
919
|
+
eq4(rootIdentity.id, rootConversation.actorIdentityId)
|
|
920
|
+
).where(inArray2(juniorConversations.conversationId, [...conversationIds]));
|
|
644
921
|
return new Map(
|
|
645
922
|
rows.map((row) => {
|
|
646
923
|
const hasValidRoot = row.rootConversationId !== null && row.rootConversationId === row.storedRootConversationId && row.rootRootConversationId === row.rootConversationId && row.rootParentConversationId === null && (row.parentConversationId !== null || row.storedRootConversationId === row.conversationId);
|
|
@@ -664,7 +941,7 @@ async function readConversationAccessFromSql(db, conversationIds, verifiedViewer
|
|
|
664
941
|
}
|
|
665
942
|
|
|
666
943
|
// src/api/conversations/usage.ts
|
|
667
|
-
import { and as
|
|
944
|
+
import { and as and4, eq as eq5, inArray as inArray3, isNull, sql as sql3 } from "drizzle-orm";
|
|
668
945
|
import { alias as alias2 } from "drizzle-orm/pg-core";
|
|
669
946
|
var usage2 = juniorConversations.usage;
|
|
670
947
|
var metricRootConversation = alias2(
|
|
@@ -678,10 +955,10 @@ var componentFields = [
|
|
|
678
955
|
"cacheCreationTokens"
|
|
679
956
|
];
|
|
680
957
|
function summedUsageNumber(field) {
|
|
681
|
-
return
|
|
958
|
+
return sql3`sum((${usage2}->>${field})::double precision)::double precision`;
|
|
682
959
|
}
|
|
683
960
|
function summedCostNumber(field) {
|
|
684
|
-
return
|
|
961
|
+
return sql3`round(
|
|
685
962
|
sum((${usage2}->'cost'->>${field})::numeric),
|
|
686
963
|
12
|
|
687
964
|
)::double precision`;
|
|
@@ -711,7 +988,7 @@ function usageFromAggregate(row) {
|
|
|
711
988
|
}
|
|
712
989
|
async function readRootConversationMetricsFromSql(db, rootConversationIds) {
|
|
713
990
|
if (rootConversationIds.length === 0) return /* @__PURE__ */ new Map();
|
|
714
|
-
const hasComponents =
|
|
991
|
+
const hasComponents = sql3`coalesce(
|
|
715
992
|
${usage2}->>'inputTokens',
|
|
716
993
|
${usage2}->>'outputTokens',
|
|
717
994
|
${usage2}->>'cachedInputTokens',
|
|
@@ -719,12 +996,12 @@ async function readRootConversationMetricsFromSql(db, rootConversationIds) {
|
|
|
719
996
|
) is not null`;
|
|
720
997
|
const rows = await db.select({
|
|
721
998
|
rootConversationId: juniorConversations.rootConversationId,
|
|
722
|
-
durationMs:
|
|
999
|
+
durationMs: sql3`coalesce(sum(${juniorConversations.durationMs}), 0)::double precision`,
|
|
723
1000
|
inputTokens: summedUsageNumber("inputTokens"),
|
|
724
1001
|
outputTokens: summedUsageNumber("outputTokens"),
|
|
725
1002
|
cachedInputTokens: summedUsageNumber("cachedInputTokens"),
|
|
726
1003
|
cacheCreationTokens: summedUsageNumber("cacheCreationTokens"),
|
|
727
|
-
totalOnlyTokens:
|
|
1004
|
+
totalOnlyTokens: sql3`sum(
|
|
728
1005
|
case
|
|
729
1006
|
when not (${hasComponents})
|
|
730
1007
|
then (${usage2}->>'totalTokens')::double precision
|
|
@@ -738,19 +1015,19 @@ async function readRootConversationMetricsFromSql(db, rootConversationIds) {
|
|
|
738
1015
|
costTotal: summedCostNumber("total")
|
|
739
1016
|
}).from(juniorConversations).innerJoin(
|
|
740
1017
|
metricRootConversation,
|
|
741
|
-
|
|
742
|
-
|
|
1018
|
+
and4(
|
|
1019
|
+
eq5(
|
|
743
1020
|
metricRootConversation.conversationId,
|
|
744
1021
|
juniorConversations.rootConversationId
|
|
745
1022
|
),
|
|
746
1023
|
isNull(metricRootConversation.parentConversationId),
|
|
747
|
-
|
|
1024
|
+
eq5(
|
|
748
1025
|
metricRootConversation.rootConversationId,
|
|
749
1026
|
metricRootConversation.conversationId
|
|
750
1027
|
)
|
|
751
1028
|
)
|
|
752
1029
|
).where(
|
|
753
|
-
|
|
1030
|
+
inArray3(juniorConversations.rootConversationId, [...rootConversationIds])
|
|
754
1031
|
).groupBy(juniorConversations.rootConversationId);
|
|
755
1032
|
return new Map(
|
|
756
1033
|
rows.flatMap((row) => {
|
|
@@ -782,22 +1059,22 @@ async function conversationRows(db, limit, actorEmail) {
|
|
|
782
1059
|
userDisplayName: juniorUsers.displayName
|
|
783
1060
|
}).from(juniorConversations).leftJoin(
|
|
784
1061
|
juniorDestinations,
|
|
785
|
-
|
|
1062
|
+
eq6(juniorDestinations.id, juniorConversations.destinationId)
|
|
786
1063
|
).leftJoin(
|
|
787
1064
|
juniorIdentities,
|
|
788
|
-
|
|
789
|
-
).leftJoin(juniorUsers,
|
|
790
|
-
|
|
1065
|
+
eq6(juniorIdentities.id, juniorConversations.actorIdentityId)
|
|
1066
|
+
).leftJoin(juniorUsers, eq6(juniorUsers.id, juniorIdentities.userId)).where(
|
|
1067
|
+
and5(
|
|
791
1068
|
isNull2(juniorConversations.parentConversationId),
|
|
792
1069
|
isNull2(juniorConversations.archivedAt),
|
|
793
|
-
actorEmail ?
|
|
794
|
-
|
|
795
|
-
|
|
1070
|
+
actorEmail ? and5(
|
|
1071
|
+
eq6(juniorIdentities.emailNormalized, actorEmail),
|
|
1072
|
+
eq6(juniorIdentities.emailVerified, true)
|
|
796
1073
|
) : void 0
|
|
797
1074
|
)
|
|
798
1075
|
).orderBy(
|
|
799
|
-
|
|
800
|
-
|
|
1076
|
+
desc2(juniorConversations.lastActivityAt),
|
|
1077
|
+
asc2(juniorConversations.conversationId)
|
|
801
1078
|
).limit(limit);
|
|
802
1079
|
}
|
|
803
1080
|
function conversationFromRow(row) {
|
|
@@ -845,11 +1122,11 @@ async function readConversationRecordFromSql(conversationId) {
|
|
|
845
1122
|
userDisplayName: juniorUsers.displayName
|
|
846
1123
|
}).from(juniorConversations).leftJoin(
|
|
847
1124
|
juniorDestinations,
|
|
848
|
-
|
|
1125
|
+
eq6(juniorDestinations.id, juniorConversations.destinationId)
|
|
849
1126
|
).leftJoin(
|
|
850
1127
|
juniorIdentities,
|
|
851
|
-
|
|
852
|
-
).leftJoin(juniorUsers,
|
|
1128
|
+
eq6(juniorIdentities.id, juniorConversations.actorIdentityId)
|
|
1129
|
+
).leftJoin(juniorUsers, eq6(juniorUsers.id, juniorIdentities.userId)).where(eq6(juniorConversations.conversationId, conversationId)).limit(1);
|
|
853
1130
|
const row = rows[0];
|
|
854
1131
|
return row ? {
|
|
855
1132
|
conversation: conversationFromRow(row),
|
|
@@ -914,35 +1191,11 @@ var list_default = defineApiRoute({
|
|
|
914
1191
|
});
|
|
915
1192
|
|
|
916
1193
|
// src/api/conversations/detail.ts
|
|
917
|
-
var conversationEventColumns = getTableColumns(juniorConversationEvents);
|
|
918
|
-
async function readConversationReportEventRows(executor, conversationId) {
|
|
919
|
-
return executor.db().select({
|
|
920
|
-
...conversationEventColumns,
|
|
921
|
-
// Replacement history is model context, never dashboard report data.
|
|
922
|
-
payload: sql3`case
|
|
923
|
-
when ${juniorConversationEvents.type} in ('compaction', 'handoff')
|
|
924
|
-
then jsonb_set(
|
|
925
|
-
${juniorConversationEvents.payload},
|
|
926
|
-
'{replacementHistory}',
|
|
927
|
-
'[]'::jsonb
|
|
928
|
-
)
|
|
929
|
-
else ${juniorConversationEvents.payload}
|
|
930
|
-
end`
|
|
931
|
-
}).from(juniorConversationEvents).where(
|
|
932
|
-
and5(
|
|
933
|
-
eq6(juniorConversationEvents.conversationId, conversationId),
|
|
934
|
-
inArray3(juniorConversationEvents.type, [
|
|
935
|
-
...conversationReportSourceEventTypes
|
|
936
|
-
])
|
|
937
|
-
)
|
|
938
|
-
).orderBy(asc2(juniorConversationEvents.seq));
|
|
939
|
-
}
|
|
940
1194
|
function projectConversationDetail(args) {
|
|
941
1195
|
const { conversation } = args;
|
|
942
1196
|
const conversationId = conversation.conversationId;
|
|
943
1197
|
const transcriptPurgedAtMs = conversation.transcriptPurgedAtMs;
|
|
944
1198
|
const canExposePayload = args.access?.canViewPrivateContent ?? false;
|
|
945
|
-
const events = transcriptPurgedAtMs === void 0 ? args.events : [];
|
|
946
1199
|
const modelUsage = transcriptPurgedAtMs === void 0 ? args.modelUsage : [];
|
|
947
1200
|
const sentryConversationUrl = buildSentryConversationUrl(conversationId);
|
|
948
1201
|
return {
|
|
@@ -953,15 +1206,18 @@ function projectConversationDetail(args) {
|
|
|
953
1206
|
...args.locationId ? { locationId: args.locationId } : {},
|
|
954
1207
|
usage: args.usage
|
|
955
1208
|
}),
|
|
956
|
-
events:
|
|
1209
|
+
events: args.events,
|
|
1210
|
+
...args.previousSeq !== void 0 ? {
|
|
1211
|
+
previousCursor: encodeConversationCursor({
|
|
1212
|
+
conversationId,
|
|
1213
|
+
seq: args.previousSeq
|
|
1214
|
+
})
|
|
1215
|
+
} : {},
|
|
957
1216
|
...modelUsage.length > 0 ? { modelUsage } : {},
|
|
958
|
-
eventHistory:
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
}
|
|
962
|
-
status: "redacted",
|
|
963
|
-
reason: "non_public_conversation"
|
|
964
|
-
},
|
|
1217
|
+
eventHistory: conversationEventHistory({
|
|
1218
|
+
canExposePayload,
|
|
1219
|
+
...transcriptPurgedAtMs === void 0 ? {} : { transcriptPurgedAtMs }
|
|
1220
|
+
}),
|
|
965
1221
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
966
1222
|
...sentryConversationUrl ? { sentryConversationUrl } : {}
|
|
967
1223
|
};
|
|
@@ -971,13 +1227,12 @@ async function readConversationDetailFromSql(conversationId, options) {
|
|
|
971
1227
|
if (!record) return void 0;
|
|
972
1228
|
const executor = getSqlExecutor();
|
|
973
1229
|
const includeDescendantMetrics = record.rootConversationId === conversationId;
|
|
974
|
-
const [accessByConversation,
|
|
1230
|
+
const [accessByConversation, modelUsage, metricsByRoot] = await Promise.all([
|
|
975
1231
|
readConversationAccessFromSql(
|
|
976
1232
|
getDb(),
|
|
977
1233
|
[conversationId],
|
|
978
1234
|
options.verifiedViewerEmail
|
|
979
1235
|
),
|
|
980
|
-
readConversationReportEventRows(executor, conversationId),
|
|
981
1236
|
record.conversation.transcriptPurgedAtMs === void 0 ? readConversationModelUsageFromSql(executor, {
|
|
982
1237
|
conversationId,
|
|
983
1238
|
includeDescendants: includeDescendantMetrics
|
|
@@ -987,29 +1242,28 @@ async function readConversationDetailFromSql(conversationId, options) {
|
|
|
987
1242
|
includeDescendantMetrics ? [conversationId] : []
|
|
988
1243
|
)
|
|
989
1244
|
]);
|
|
990
|
-
const
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
createdAtMs: row.createdAt.getTime(),
|
|
997
|
-
type: row.type,
|
|
998
|
-
payload: row.payload
|
|
999
|
-
})
|
|
1000
|
-
);
|
|
1245
|
+
const access = accessByConversation.get(conversationId);
|
|
1246
|
+
const page = record.conversation.transcriptPurgedAtMs === void 0 ? await readConversationEventPage(executor, {
|
|
1247
|
+
canExposePayload: access?.canViewPrivateContent ?? false,
|
|
1248
|
+
conversationId,
|
|
1249
|
+
limit: options.limit
|
|
1250
|
+
}) : { events: [] };
|
|
1001
1251
|
const metrics = metricsByRoot.get(conversationId);
|
|
1002
1252
|
return projectConversationDetail({
|
|
1003
1253
|
...record,
|
|
1004
|
-
access
|
|
1254
|
+
access,
|
|
1005
1255
|
durationMs: metrics?.durationMs ?? record.durationMs,
|
|
1006
|
-
events,
|
|
1256
|
+
events: page.events,
|
|
1007
1257
|
modelUsage,
|
|
1258
|
+
...page.previousSeq === void 0 ? {} : { previousSeq: page.previousSeq },
|
|
1008
1259
|
usage: metrics?.usage ?? record.usage ?? void 0
|
|
1009
1260
|
});
|
|
1010
1261
|
}
|
|
1011
1262
|
async function readConversationDetail(conversationId, options = {}) {
|
|
1012
|
-
const report = await readConversationDetailFromSql(conversationId,
|
|
1263
|
+
const report = await readConversationDetailFromSql(conversationId, {
|
|
1264
|
+
...options,
|
|
1265
|
+
limit: options.limit ?? 500
|
|
1266
|
+
});
|
|
1013
1267
|
return report ? conversationDetailReportSchema.parse(report) : void 0;
|
|
1014
1268
|
}
|
|
1015
1269
|
var detail_default = defineApiRoute({
|
|
@@ -1021,11 +1275,73 @@ var detail_default = defineApiRoute({
|
|
|
1021
1275
|
conversationParamsSchema,
|
|
1022
1276
|
c.req.param()
|
|
1023
1277
|
);
|
|
1278
|
+
const query = parseQuery(conversationDetailQuerySchema, c.req.query());
|
|
1024
1279
|
const verifiedViewerEmail = c.get("verifiedViewerEmail");
|
|
1025
|
-
const report = await readConversationDetail(
|
|
1026
|
-
|
|
1027
|
-
verifiedViewerEmail ? { verifiedViewerEmail } : {}
|
|
1280
|
+
const report = await readConversationDetail(conversationId, {
|
|
1281
|
+
...query,
|
|
1282
|
+
...verifiedViewerEmail ? { verifiedViewerEmail } : {}
|
|
1283
|
+
});
|
|
1284
|
+
if (!report) throwApiError(404, "Conversation not found.");
|
|
1285
|
+
return report;
|
|
1286
|
+
}
|
|
1287
|
+
});
|
|
1288
|
+
|
|
1289
|
+
// src/api/conversations/event-list.ts
|
|
1290
|
+
async function readConversationEvents(conversationId, beforeValue, options = {}) {
|
|
1291
|
+
const record = await readConversationRecordFromSql(conversationId);
|
|
1292
|
+
if (!record) return void 0;
|
|
1293
|
+
const before = decodeConversationCursor({
|
|
1294
|
+
conversationId,
|
|
1295
|
+
cursor: beforeValue
|
|
1296
|
+
});
|
|
1297
|
+
if (!before) throwApiError(400, "Invalid conversation cursor.");
|
|
1298
|
+
const accessByConversation = await readConversationAccessFromSql(
|
|
1299
|
+
getDb(),
|
|
1300
|
+
[conversationId],
|
|
1301
|
+
options.verifiedViewerEmail
|
|
1302
|
+
);
|
|
1303
|
+
const access = accessByConversation.get(conversationId);
|
|
1304
|
+
const canExposePayload = access?.canViewPrivateContent ?? false;
|
|
1305
|
+
const transcriptPurgedAtMs = record.conversation.transcriptPurgedAtMs;
|
|
1306
|
+
const page = transcriptPurgedAtMs === void 0 ? await readConversationEventPage(getSqlExecutor(), {
|
|
1307
|
+
beforeSeq: before.seq,
|
|
1308
|
+
canExposePayload,
|
|
1309
|
+
conversationId,
|
|
1310
|
+
limit: options.limit ?? 500
|
|
1311
|
+
}) : { events: [] };
|
|
1312
|
+
return conversationEventPageSchema.parse({
|
|
1313
|
+
events: page.events,
|
|
1314
|
+
eventHistory: conversationEventHistory({
|
|
1315
|
+
canExposePayload,
|
|
1316
|
+
...transcriptPurgedAtMs === void 0 ? {} : { transcriptPurgedAtMs }
|
|
1317
|
+
}),
|
|
1318
|
+
...page.previousSeq === void 0 ? {} : {
|
|
1319
|
+
previousCursor: encodeConversationCursor({
|
|
1320
|
+
conversationId,
|
|
1321
|
+
seq: page.previousSeq
|
|
1322
|
+
})
|
|
1323
|
+
},
|
|
1324
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1325
|
+
});
|
|
1326
|
+
}
|
|
1327
|
+
var event_list_default = defineApiRoute({
|
|
1328
|
+
method: "get",
|
|
1329
|
+
path: "/:conversationId/events",
|
|
1330
|
+
responseSchema: conversationEventPageSchema,
|
|
1331
|
+
handler: async (c) => {
|
|
1332
|
+
const { conversationId } = parseParams(
|
|
1333
|
+
conversationParamsSchema,
|
|
1334
|
+
c.req.param()
|
|
1028
1335
|
);
|
|
1336
|
+
const { before, limit } = parseQuery(
|
|
1337
|
+
conversationEventsQuerySchema,
|
|
1338
|
+
c.req.query()
|
|
1339
|
+
);
|
|
1340
|
+
const verifiedViewerEmail = c.get("verifiedViewerEmail");
|
|
1341
|
+
const report = await readConversationEvents(conversationId, before, {
|
|
1342
|
+
limit,
|
|
1343
|
+
...verifiedViewerEmail ? { verifiedViewerEmail } : {}
|
|
1344
|
+
});
|
|
1029
1345
|
if (!report) throwApiError(404, "Conversation not found.");
|
|
1030
1346
|
return report;
|
|
1031
1347
|
}
|
|
@@ -1325,7 +1641,13 @@ var stats_default = defineApiRoute({
|
|
|
1325
1641
|
});
|
|
1326
1642
|
|
|
1327
1643
|
// src/api/conversations/routes.ts
|
|
1328
|
-
var routes = [
|
|
1644
|
+
var routes = [
|
|
1645
|
+
list_default,
|
|
1646
|
+
stats_default,
|
|
1647
|
+
archive_default,
|
|
1648
|
+
event_list_default,
|
|
1649
|
+
detail_default
|
|
1650
|
+
];
|
|
1329
1651
|
function createConversationRoutes() {
|
|
1330
1652
|
const app = new Hono();
|
|
1331
1653
|
registerApiRoutes(app, routes);
|
|
@@ -1336,7 +1658,7 @@ function createConversationRoutes() {
|
|
|
1336
1658
|
import { Hono as Hono2 } from "hono";
|
|
1337
1659
|
|
|
1338
1660
|
// src/api/locations/query.ts
|
|
1339
|
-
import { and as and7, asc as asc3, desc as
|
|
1661
|
+
import { and as and7, asc as asc3, desc as desc3, eq as eq8, gte as gte2, isNull as isNull4, sql as sql6 } from "drizzle-orm";
|
|
1340
1662
|
import { alias as alias4 } from "drizzle-orm/pg-core";
|
|
1341
1663
|
|
|
1342
1664
|
// src/api/conversations/reporting.ts
|
|
@@ -1622,7 +1944,7 @@ async function recentLocationRows(db, locationId) {
|
|
|
1622
1944
|
isNull4(juniorConversations.archivedAt)
|
|
1623
1945
|
)
|
|
1624
1946
|
).orderBy(
|
|
1625
|
-
|
|
1947
|
+
desc3(juniorConversations.lastActivityAt),
|
|
1626
1948
|
asc3(juniorConversations.conversationId)
|
|
1627
1949
|
).limit(RECENT_LIMIT);
|
|
1628
1950
|
}
|
|
@@ -1803,7 +2125,7 @@ import { Hono as Hono3 } from "hono";
|
|
|
1803
2125
|
import { and as and9, eq as eq10, gte as gte3, sql as sql8 } from "drizzle-orm";
|
|
1804
2126
|
|
|
1805
2127
|
// src/api/people/shared.ts
|
|
1806
|
-
import { and as and8, asc as asc4, desc as
|
|
2128
|
+
import { and as and8, asc as asc4, desc as desc4, eq as eq9, isNull as isNull5, notExists, or, sql as sql7 } from "drizzle-orm";
|
|
1807
2129
|
import { alias as alias5 } from "drizzle-orm/pg-core";
|
|
1808
2130
|
var RECENT_LIMIT2 = 25;
|
|
1809
2131
|
var ACTIVITY_DAYS2 = 365;
|
|
@@ -1937,7 +2259,7 @@ async function recentActorRows(email) {
|
|
|
1937
2259
|
).where(
|
|
1938
2260
|
and8(verifiedActorWhere(email), isNull5(juniorConversations.archivedAt))
|
|
1939
2261
|
).orderBy(
|
|
1940
|
-
|
|
2262
|
+
desc4(juniorConversations.lastActivityAt),
|
|
1941
2263
|
asc4(juniorConversations.conversationId)
|
|
1942
2264
|
).limit(RECENT_LIMIT2);
|
|
1943
2265
|
}
|
|
@@ -2257,7 +2579,7 @@ function readDescriptionText(home) {
|
|
|
2257
2579
|
}
|
|
2258
2580
|
}
|
|
2259
2581
|
async function readSkillReports() {
|
|
2260
|
-
const { discoverSkills } = await import("./skills-
|
|
2582
|
+
const { discoverSkills } = await import("./skills-QCNZISNF.js");
|
|
2261
2583
|
const skills = await discoverSkills();
|
|
2262
2584
|
return skillReportsSchema.parse(
|
|
2263
2585
|
skills.map((skill) => ({
|
|
@@ -2267,7 +2589,7 @@ async function readSkillReports() {
|
|
|
2267
2589
|
);
|
|
2268
2590
|
}
|
|
2269
2591
|
async function readPluginReports() {
|
|
2270
|
-
const { pluginCatalogRuntime } = await import("./catalog-runtime-
|
|
2592
|
+
const { pluginCatalogRuntime } = await import("./catalog-runtime-6O4M6JGA.js");
|
|
2271
2593
|
return pluginReportsSchema.parse(
|
|
2272
2594
|
pluginCatalogRuntime.getProviders().map((plugin) => ({
|
|
2273
2595
|
name: plugin.manifest.name
|
|
@@ -2277,7 +2599,7 @@ async function readPluginReports() {
|
|
|
2277
2599
|
async function readRuntimeInfoReport() {
|
|
2278
2600
|
const [{ homeDir }, { pluginCatalogRuntime }, plugins, skills] = await Promise.all([
|
|
2279
2601
|
import("./discovery-RMHYSRL7.js"),
|
|
2280
|
-
import("./catalog-runtime-
|
|
2602
|
+
import("./catalog-runtime-6O4M6JGA.js"),
|
|
2281
2603
|
readPluginReports(),
|
|
2282
2604
|
readSkillReports()
|
|
2283
2605
|
]);
|
|
@@ -2293,7 +2615,7 @@ async function readRuntimeInfoReport() {
|
|
|
2293
2615
|
}
|
|
2294
2616
|
async function readPluginOperationalReportFeed() {
|
|
2295
2617
|
const nowMs = Date.now();
|
|
2296
|
-
const { getPluginOperationalReports } = await import("./agent-hooks-
|
|
2618
|
+
const { getPluginOperationalReports } = await import("./agent-hooks-WNBUY4OB.js");
|
|
2297
2619
|
return pluginOperationalReportFeedSchema.parse({
|
|
2298
2620
|
source: "plugins",
|
|
2299
2621
|
generatedAt: new Date(nowMs).toISOString(),
|