@sentry/junior 0.99.0 → 0.100.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-OSW6C3CJ.js → agent-hooks-V6KU7PQN.js} +6 -5
- package/dist/api/activity.d.ts +14 -0
- package/dist/api/conversations/aggregate.d.ts +16 -0
- package/dist/api/conversations/detail-projection.d.ts +1 -0
- package/dist/api/conversations/list.query.d.ts +3 -0
- package/dist/api/conversations/projection.d.ts +1 -0
- package/dist/api/conversations/reporting.d.ts +42 -0
- package/dist/api/conversations/schema.d.ts +7 -7
- package/dist/api/conversations/stats.query.d.ts +1 -1
- package/dist/api/locations/detail.d.ts +81 -0
- package/dist/api/locations/list.d.ts +30 -0
- package/dist/api/locations/query.d.ts +5 -0
- package/dist/api/locations/schema.d.ts +175 -0
- package/dist/api/people/list.query.d.ts +1 -1
- package/dist/api/people/profile.query.d.ts +1 -1
- package/dist/api/people/schema.d.ts +10 -14
- package/dist/api/people/shared.d.ts +38 -78
- package/dist/api/schema.d.ts +8 -0
- package/dist/api/schema.js +14 -3
- package/dist/api.js +24 -11
- package/dist/app.js +25 -19
- package/dist/chat/agent/request.d.ts +3 -0
- package/dist/chat/config.d.ts +2 -0
- package/dist/chat/reasoning-level.d.ts +4 -0
- package/dist/chat/services/{turn-thinking-level.d.ts → turn-reasoning-level.d.ts} +11 -10
- package/dist/chat/services/turn-result.d.ts +3 -3
- package/dist/chat/tools/search-tools.d.ts +2 -2
- package/dist/{chunk-T55RBE4Z.js → chunk-2RNOB32R.js} +3 -1
- package/dist/{chunk-NJEDJFK4.js → chunk-2T7DCRAW.js} +1 -1
- package/dist/{chunk-PYK7R5A7.js → chunk-45DMFMY2.js} +66 -65
- package/dist/chunk-4AQUWWEM.js +75 -0
- package/dist/{chunk-EEZCY5WX.js → chunk-A7X2FDUO.js} +18 -2
- package/dist/{chunk-WTYEKPXU.js → chunk-FP5N5OWZ.js} +1 -1
- package/dist/chunk-FXFQNHRU.js +48 -0
- package/dist/chunk-GEUUJRQF.js +102 -0
- package/dist/{chunk-CRQVIHDI.js → chunk-IDZBM3NW.js} +2 -8
- package/dist/{chunk-DHHU2WSG.js → chunk-IQIBZXGB.js} +2 -2
- package/dist/{chunk-OL6XQ23W.js → chunk-IVXL57YF.js} +3 -3
- package/dist/{chunk-IO65E4ZD.js → chunk-JPQISMMJ.js} +3 -3
- package/dist/{chunk-KFUSLFLL.js → chunk-JSAANELJ.js} +11 -4
- package/dist/{chunk-EUZ44ROE.js → chunk-MM5UFDAC.js} +1 -3
- package/dist/{chunk-WJ7STXT6.js → chunk-NSOCZGOH.js} +3 -3
- package/dist/chunk-PGGEOCQY.js +77 -0
- package/dist/{chunk-EOWXRY5E.js → chunk-PWC24W5F.js} +1 -1
- package/dist/chunk-QOZOJNSE.js +96 -0
- package/dist/chunk-QSBQJ3PA.js +275 -0
- package/dist/{chunk-FTTFV6DC.js → chunk-TPTJEHUE.js} +4 -4
- package/dist/{chunk-OGHXZ4KQ.js → chunk-VHRM6GNH.js} +88 -122
- package/dist/{chunk-NG2AV7IB.js → chunk-VVIXK2BX.js} +1 -1
- package/dist/{chunk-ZZUBLPXD.js → chunk-VY7BT4SM.js} +5 -4
- package/dist/{chunk-H66UCBPW.js → chunk-XJA7BPHS.js} +1 -1
- package/dist/{chunk-ER45IV77.js → chunk-XSBIISXS.js} +9 -9
- package/dist/cli/chat.js +15 -14
- package/dist/cli/plugins.js +6 -5
- package/dist/cli/snapshot-warmup.js +2 -2
- package/dist/cli/upgrade.js +8 -7
- package/dist/db/schema/conversations.d.ts +17 -0
- package/dist/db/schema/destinations.d.ts +12 -3
- package/dist/db/schema.d.ts +19 -2
- package/dist/{db-GFSCDAHS.js → db-RCZB7KNM.js} +3 -2
- package/dist/detail-5SLCGT6J.js +29 -0
- package/dist/{detail-Q4IVDNGS.js → detail-LU6COZO6.js} +11 -10
- package/dist/{legacy-import-6WWXMALY.js → legacy-import-VCYLWT2V.js} +4 -3
- package/dist/list-2FI5SFV7.js +80 -0
- package/dist/list-4ALSU6ZW.js +30 -0
- package/dist/{list-A3F5JDYV.js → list-KHRAWZWU.js} +7 -6
- package/dist/{plugin-conversations-PDCQWU3O.js → plugin-conversations-JANXC4GA.js} +6 -5
- package/dist/profile-3O3OVENT.js +212 -0
- package/dist/{runner-267ZRLZD.js → runner-BM7D35YW.js} +12 -11
- package/dist/stats-J3YGCYDF.js +174 -0
- package/dist/{subagent-UN3MP6LV.js → subagent-P7HOSMVC.js} +10 -9
- package/migrations/0003_peaceful_scalphunter.sql +4 -0
- package/migrations/meta/0003_snapshot.json +1035 -0
- package/migrations/meta/_journal.json +8 -1
- package/package.json +5 -5
- package/dist/chunk-CV22LUIV.js +0 -261
- package/dist/list-M5BRWW3D.js +0 -92
- package/dist/profile-UEIRSVT3.js +0 -146
- package/dist/stats-L62E4O4U.js +0 -207
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getDb,
|
|
3
|
+
juniorConversations,
|
|
4
|
+
juniorIdentities,
|
|
5
|
+
juniorUsers
|
|
6
|
+
} from "./chunk-VHRM6GNH.js";
|
|
7
|
+
import {
|
|
8
|
+
juniorDestinations
|
|
9
|
+
} from "./chunk-FXFQNHRU.js";
|
|
10
|
+
|
|
11
|
+
// src/api/people/shared.ts
|
|
12
|
+
import { and, asc, desc, eq, sql } from "drizzle-orm";
|
|
13
|
+
var RECENT_LIMIT = 25;
|
|
14
|
+
var ACTIVITY_DAYS = 366;
|
|
15
|
+
function normalizeEmail(email) {
|
|
16
|
+
const normalized = email?.trim().toLowerCase();
|
|
17
|
+
return normalized || void 0;
|
|
18
|
+
}
|
|
19
|
+
function emptyTotals() {
|
|
20
|
+
return {
|
|
21
|
+
active: 0,
|
|
22
|
+
activeDays: 0,
|
|
23
|
+
conversations: 0,
|
|
24
|
+
durationMs: 0,
|
|
25
|
+
failed: 0
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function emptyActivityDay(date) {
|
|
29
|
+
return {
|
|
30
|
+
active: 0,
|
|
31
|
+
conversations: 0,
|
|
32
|
+
date,
|
|
33
|
+
durationMs: 0,
|
|
34
|
+
failed: 0
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
function activityDays(days, nowMs) {
|
|
38
|
+
const items = [];
|
|
39
|
+
const end = new Date(nowMs);
|
|
40
|
+
end.setUTCHours(0, 0, 0, 0);
|
|
41
|
+
const start = new Date(end);
|
|
42
|
+
start.setUTCDate(start.getUTCDate() - (ACTIVITY_DAYS - 1));
|
|
43
|
+
for (const cursor = new Date(start); cursor.getTime() <= end.getTime(); cursor.setUTCDate(cursor.getUTCDate() + 1)) {
|
|
44
|
+
const date = cursor.toISOString().slice(0, 10);
|
|
45
|
+
items.push(days.get(date) ?? emptyActivityDay(date));
|
|
46
|
+
}
|
|
47
|
+
return items;
|
|
48
|
+
}
|
|
49
|
+
function statsItems(map) {
|
|
50
|
+
return [...map.values()].sort(
|
|
51
|
+
(left, right) => right.conversations - left.conversations || right.durationMs - left.durationMs || left.label.localeCompare(right.label)
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
function verifiedActorWhere(email) {
|
|
55
|
+
const normalizedEmail = normalizeEmail(email);
|
|
56
|
+
return and(
|
|
57
|
+
eq(juniorIdentities.provider, "slack"),
|
|
58
|
+
eq(juniorIdentities.emailVerified, true),
|
|
59
|
+
sql`${juniorUsers.primaryEmailNormalized} IS NOT NULL`,
|
|
60
|
+
normalizedEmail ? eq(juniorUsers.primaryEmailNormalized, normalizedEmail) : void 0
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
async function recentActorRows(email) {
|
|
64
|
+
return getDb().select({
|
|
65
|
+
channelName: juniorConversations.channelName,
|
|
66
|
+
conversationId: juniorConversations.conversationId,
|
|
67
|
+
createdAt: juniorConversations.createdAt,
|
|
68
|
+
destinationId: juniorDestinations.id,
|
|
69
|
+
destinationVisibility: juniorDestinations.visibility,
|
|
70
|
+
durationMs: juniorConversations.durationMs,
|
|
71
|
+
email: juniorUsers.primaryEmailNormalized,
|
|
72
|
+
executionStatus: juniorConversations.executionStatus,
|
|
73
|
+
executionUpdatedAt: juniorConversations.executionUpdatedAt,
|
|
74
|
+
fullName: juniorUsers.displayName,
|
|
75
|
+
handle: juniorIdentities.handle,
|
|
76
|
+
lastActivityAt: juniorConversations.lastActivityAt,
|
|
77
|
+
providerSubjectId: juniorIdentities.providerSubjectId,
|
|
78
|
+
source: juniorConversations.source,
|
|
79
|
+
title: juniorConversations.title,
|
|
80
|
+
updatedAt: juniorConversations.updatedAt,
|
|
81
|
+
usage: juniorConversations.usage
|
|
82
|
+
}).from(juniorConversations).innerJoin(
|
|
83
|
+
juniorIdentities,
|
|
84
|
+
eq(juniorIdentities.id, juniorConversations.actorIdentityId)
|
|
85
|
+
).innerJoin(juniorUsers, eq(juniorUsers.id, juniorIdentities.userId)).leftJoin(
|
|
86
|
+
juniorDestinations,
|
|
87
|
+
eq(juniorDestinations.id, juniorConversations.destinationId)
|
|
88
|
+
).where(verifiedActorWhere(email)).orderBy(
|
|
89
|
+
desc(juniorConversations.lastActivityAt),
|
|
90
|
+
asc(juniorConversations.conversationId)
|
|
91
|
+
).limit(RECENT_LIMIT);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export {
|
|
95
|
+
ACTIVITY_DAYS,
|
|
96
|
+
normalizeEmail,
|
|
97
|
+
emptyTotals,
|
|
98
|
+
activityDays,
|
|
99
|
+
statsItems,
|
|
100
|
+
verifiedActorWhere,
|
|
101
|
+
recentActorRows
|
|
102
|
+
};
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
actorIdentitySchema,
|
|
3
3
|
conversationStatsItemSchema,
|
|
4
4
|
conversationSummaryReportSchema
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-MM5UFDAC.js";
|
|
6
6
|
|
|
7
7
|
// src/api/people/schema.ts
|
|
8
8
|
import { z } from "zod";
|
|
@@ -37,10 +37,7 @@ var actorSummaryReportSchema = actorTotalsReportSchema.extend({
|
|
|
37
37
|
var actorDirectoryReportSchema = z.object({
|
|
38
38
|
generatedAt: z.string(),
|
|
39
39
|
people: z.array(actorSummaryReportSchema),
|
|
40
|
-
|
|
41
|
-
sampleSize: z.number(),
|
|
42
|
-
source: z.literal("conversation_index"),
|
|
43
|
-
truncated: z.boolean()
|
|
40
|
+
source: z.literal("conversation_index")
|
|
44
41
|
}).strict();
|
|
45
42
|
var actorProfileReportSchema = z.object({
|
|
46
43
|
activityDays: z.array(actorActivityDayReportSchema),
|
|
@@ -48,12 +45,9 @@ var actorProfileReportSchema = z.object({
|
|
|
48
45
|
locations: z.array(peopleConversationStatsItemSchema),
|
|
49
46
|
recentConversations: z.array(peopleConversationSummaryReportSchema),
|
|
50
47
|
actor: identifiedActorSchema,
|
|
51
|
-
sampleLimit: z.number(),
|
|
52
|
-
sampleSize: z.number(),
|
|
53
48
|
source: z.literal("conversation_index"),
|
|
54
49
|
surfaces: z.array(peopleConversationStatsItemSchema),
|
|
55
50
|
totals: actorTotalsReportSchema,
|
|
56
|
-
truncated: z.boolean(),
|
|
57
51
|
windowEnd: z.string(),
|
|
58
52
|
windowStart: z.string()
|
|
59
53
|
}).strict();
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ensureLegacyConversationImport
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-JPQISMMJ.js";
|
|
4
4
|
import {
|
|
5
5
|
contextProvenance,
|
|
6
6
|
getAgentStepStore
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-VHRM6GNH.js";
|
|
8
8
|
|
|
9
9
|
// src/chat/conversations/projection.ts
|
|
10
10
|
import { isDeepStrictEqual } from "util";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
commitMessages,
|
|
3
3
|
loadTurnProjection
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-IQIBZXGB.js";
|
|
5
5
|
import {
|
|
6
6
|
usageSchema
|
|
7
7
|
} from "./chunk-PDO5BLNM.js";
|
|
@@ -9,10 +9,10 @@ import {
|
|
|
9
9
|
getConversationStore,
|
|
10
10
|
instructionActors,
|
|
11
11
|
instructionProvenanceFor
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-VHRM6GNH.js";
|
|
13
13
|
import {
|
|
14
14
|
getStateAdapter
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-A7X2FDUO.js";
|
|
16
16
|
import {
|
|
17
17
|
toStoredSlackActor
|
|
18
18
|
} from "./chunk-I35CTGPO.js";
|
|
@@ -11,14 +11,14 @@ import {
|
|
|
11
11
|
legacyActorProvenance,
|
|
12
12
|
piMessageSchema,
|
|
13
13
|
readSessionLogEntries
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-VHRM6GNH.js";
|
|
15
15
|
import {
|
|
16
16
|
botConfig,
|
|
17
17
|
escapeXml,
|
|
18
18
|
getStateAdapter,
|
|
19
19
|
resolveGatewayModel,
|
|
20
20
|
unescapeXml
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-A7X2FDUO.js";
|
|
22
22
|
import {
|
|
23
23
|
logWarn,
|
|
24
24
|
setSpanAttributes
|
|
@@ -464,7 +464,7 @@ async function hydrateConversationMessages(args) {
|
|
|
464
464
|
args.conversation.messages = [];
|
|
465
465
|
return;
|
|
466
466
|
}
|
|
467
|
-
const { ensureLegacyConversationImport: ensureLegacyConversationImport2 } = await import("./legacy-import-
|
|
467
|
+
const { ensureLegacyConversationImport: ensureLegacyConversationImport2 } = await import("./legacy-import-VCYLWT2V.js");
|
|
468
468
|
await ensureLegacyConversationImport2({ conversationId: args.conversationId });
|
|
469
469
|
await hydrateConversationCompactions({
|
|
470
470
|
conversation: args.conversation,
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
formatSlackConversationRedactedLabel,
|
|
3
3
|
resolveSlackConversationContextFromThreadId
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-VVIXK2BX.js";
|
|
5
5
|
import {
|
|
6
6
|
getDb,
|
|
7
7
|
juniorConversations,
|
|
8
|
-
juniorDestinations,
|
|
9
8
|
juniorIdentities
|
|
10
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-VHRM6GNH.js";
|
|
10
|
+
import {
|
|
11
|
+
juniorDestinations
|
|
12
|
+
} from "./chunk-FXFQNHRU.js";
|
|
11
13
|
import {
|
|
12
14
|
parseSlackThreadId,
|
|
13
15
|
resolveConversationPrivacy
|
|
@@ -148,7 +150,8 @@ function conversationSummaryFromStoredConversation(args) {
|
|
|
148
150
|
...actorIdentity ? { actorIdentity } : {},
|
|
149
151
|
...slackThread ? { channel: slackThread.channelId } : {},
|
|
150
152
|
...channelName ? { channelName } : {},
|
|
151
|
-
...channelNameRedacted ? { channelNameRedacted: true } : {}
|
|
153
|
+
...channelNameRedacted ? { channelNameRedacted: true } : {},
|
|
154
|
+
...args.locationId && !channelNameRedacted ? { locationId: args.locationId } : {}
|
|
152
155
|
};
|
|
153
156
|
}
|
|
154
157
|
|
|
@@ -157,6 +160,7 @@ var CONVERSATION_FEED_LIMIT = 50;
|
|
|
157
160
|
async function conversationRows(db, limit, actorEmail) {
|
|
158
161
|
return db.select({
|
|
159
162
|
conversation: juniorConversations,
|
|
163
|
+
destinationId: juniorDestinations.id,
|
|
160
164
|
destinationVisibility: juniorDestinations.visibility,
|
|
161
165
|
identityDisplayName: juniorIdentities.displayName,
|
|
162
166
|
identityEmail: juniorIdentities.email,
|
|
@@ -218,6 +222,7 @@ async function readConversationRecordFromSql(conversationId) {
|
|
|
218
222
|
const db = getDb();
|
|
219
223
|
const rows = await db.select({
|
|
220
224
|
conversation: juniorConversations,
|
|
225
|
+
destinationId: juniorDestinations.id,
|
|
221
226
|
destinationVisibility: juniorDestinations.visibility,
|
|
222
227
|
identityDisplayName: juniorIdentities.displayName,
|
|
223
228
|
identityEmail: juniorIdentities.email,
|
|
@@ -236,6 +241,7 @@ async function readConversationRecordFromSql(conversationId) {
|
|
|
236
241
|
return row ? {
|
|
237
242
|
conversation: conversationFromRow(row),
|
|
238
243
|
durationMs: row.conversation.durationMs,
|
|
244
|
+
...row.destinationVisibility === "public" && row.destinationId ? { locationId: row.destinationId } : {},
|
|
239
245
|
usage: row.conversation.usage
|
|
240
246
|
} : void 0;
|
|
241
247
|
}
|
|
@@ -251,6 +257,7 @@ async function readConversationFeedFromSql(options = {}) {
|
|
|
251
257
|
(row) => conversationSummaryFromStoredConversation({
|
|
252
258
|
conversation: conversationFromRow(row),
|
|
253
259
|
durationMs: row.conversation.durationMs,
|
|
260
|
+
...row.destinationVisibility === "public" && row.destinationId ? { locationId: row.destinationId } : {},
|
|
254
261
|
usage: row.conversation.usage ?? void 0
|
|
255
262
|
})
|
|
256
263
|
),
|
|
@@ -36,6 +36,7 @@ var conversationSummaryReportSchema = z.object({
|
|
|
36
36
|
channel: z.string().optional(),
|
|
37
37
|
channelName: z.string().optional(),
|
|
38
38
|
channelNameRedacted: z.boolean().optional(),
|
|
39
|
+
locationId: z.string().optional(),
|
|
39
40
|
sentryTraceUrl: z.string().optional(),
|
|
40
41
|
traceId: z.string().optional()
|
|
41
42
|
}).strict();
|
|
@@ -195,12 +196,9 @@ var conversationStatsReportSchema = z.object({
|
|
|
195
196
|
generatedAt: z.string(),
|
|
196
197
|
locations: z.array(conversationStatsItemSchema),
|
|
197
198
|
actors: z.array(conversationStatsItemSchema),
|
|
198
|
-
sampleLimit: z.number(),
|
|
199
|
-
sampleSize: z.number(),
|
|
200
199
|
source: z.literal("conversation_index"),
|
|
201
200
|
costUsd: z.number().optional(),
|
|
202
201
|
tokens: z.number().optional(),
|
|
203
|
-
truncated: z.boolean(),
|
|
204
202
|
windowEnd: z.string(),
|
|
205
203
|
windowStart: z.string()
|
|
206
204
|
}).strict();
|
|
@@ -7,10 +7,10 @@ import {
|
|
|
7
7
|
addAgentTurnUsage,
|
|
8
8
|
getAgentTurnSessionRecord,
|
|
9
9
|
upsertAgentTurnSessionRecord
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-IVXL57YF.js";
|
|
11
11
|
import {
|
|
12
12
|
persistConversationMessages
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-JPQISMMJ.js";
|
|
14
14
|
import {
|
|
15
15
|
sleep
|
|
16
16
|
} from "./chunk-4ZNGQH7C.js";
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
getPiMessageRole,
|
|
19
19
|
getStateAdapter,
|
|
20
20
|
trimTrailingAssistantMessages
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-A7X2FDUO.js";
|
|
22
22
|
import {
|
|
23
23
|
getActiveTraceId,
|
|
24
24
|
logException
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import {
|
|
2
|
+
juniorConversations
|
|
3
|
+
} from "./chunk-VHRM6GNH.js";
|
|
4
|
+
|
|
5
|
+
// src/api/conversations/aggregate.ts
|
|
6
|
+
import { sql } from "drizzle-orm";
|
|
7
|
+
function tokenValue() {
|
|
8
|
+
return sql`
|
|
9
|
+
CASE
|
|
10
|
+
WHEN ${juniorConversations.usage}->>'totalTokens' IS NOT NULL
|
|
11
|
+
THEN (${juniorConversations.usage}->>'totalTokens')::double precision
|
|
12
|
+
WHEN COALESCE(
|
|
13
|
+
${juniorConversations.usage}->>'inputTokens',
|
|
14
|
+
${juniorConversations.usage}->>'outputTokens',
|
|
15
|
+
${juniorConversations.usage}->>'cachedInputTokens',
|
|
16
|
+
${juniorConversations.usage}->>'cacheCreationTokens'
|
|
17
|
+
) IS NOT NULL
|
|
18
|
+
THEN COALESCE((${juniorConversations.usage}->>'inputTokens')::double precision, 0)
|
|
19
|
+
+ COALESCE((${juniorConversations.usage}->>'outputTokens')::double precision, 0)
|
|
20
|
+
+ COALESCE((${juniorConversations.usage}->>'cachedInputTokens')::double precision, 0)
|
|
21
|
+
+ COALESCE((${juniorConversations.usage}->>'cacheCreationTokens')::double precision, 0)
|
|
22
|
+
ELSE NULL
|
|
23
|
+
END
|
|
24
|
+
`;
|
|
25
|
+
}
|
|
26
|
+
function costValue() {
|
|
27
|
+
return sql`
|
|
28
|
+
CASE
|
|
29
|
+
WHEN ${juniorConversations.usage}->'cost'->>'total' IS NOT NULL
|
|
30
|
+
THEN (${juniorConversations.usage}->'cost'->>'total')::double precision
|
|
31
|
+
WHEN COALESCE(
|
|
32
|
+
${juniorConversations.usage}->'cost'->>'input',
|
|
33
|
+
${juniorConversations.usage}->'cost'->>'output',
|
|
34
|
+
${juniorConversations.usage}->'cost'->>'cacheRead',
|
|
35
|
+
${juniorConversations.usage}->'cost'->>'cacheWrite'
|
|
36
|
+
) IS NOT NULL
|
|
37
|
+
THEN COALESCE((${juniorConversations.usage}->'cost'->>'input')::double precision, 0)
|
|
38
|
+
+ COALESCE((${juniorConversations.usage}->'cost'->>'output')::double precision, 0)
|
|
39
|
+
+ COALESCE((${juniorConversations.usage}->'cost'->>'cacheRead')::double precision, 0)
|
|
40
|
+
+ COALESCE((${juniorConversations.usage}->'cost'->>'cacheWrite')::double precision, 0)
|
|
41
|
+
ELSE NULL
|
|
42
|
+
END
|
|
43
|
+
`;
|
|
44
|
+
}
|
|
45
|
+
function conversationAggregateColumns() {
|
|
46
|
+
return {
|
|
47
|
+
active: sql`COUNT(*) FILTER (
|
|
48
|
+
WHERE ${juniorConversations.executionStatus} NOT IN ('idle', 'failed')
|
|
49
|
+
)::integer`,
|
|
50
|
+
conversations: sql`COUNT(*)::integer`,
|
|
51
|
+
costUsd: sql`SUM(${costValue()})::double precision`,
|
|
52
|
+
durationMs: sql`COALESCE(SUM(${juniorConversations.durationMs}), 0)::double precision`,
|
|
53
|
+
failed: sql`COUNT(*) FILTER (
|
|
54
|
+
WHERE ${juniorConversations.executionStatus} = 'failed'
|
|
55
|
+
)::integer`,
|
|
56
|
+
tokens: sql`SUM(${tokenValue()})::double precision`
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
function conversationRangeColumns() {
|
|
60
|
+
return {
|
|
61
|
+
firstSeenAt: sql`MIN(${juniorConversations.createdAt})`.mapWith(
|
|
62
|
+
juniorConversations.createdAt
|
|
63
|
+
),
|
|
64
|
+
lastSeenAt: sql`MAX(${juniorConversations.lastActivityAt})`.mapWith(
|
|
65
|
+
juniorConversations.lastActivityAt
|
|
66
|
+
)
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
function conversationActiveDaysColumn() {
|
|
70
|
+
return sql`COUNT(DISTINCT (${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC')::date)::integer`;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export {
|
|
74
|
+
conversationAggregateColumns,
|
|
75
|
+
conversationRangeColumns,
|
|
76
|
+
conversationActiveDaysColumn
|
|
77
|
+
};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// src/api/conversations/reporting.ts
|
|
2
|
+
var PRIVATE_CONVERSATION_LABEL = "Private Conversation";
|
|
3
|
+
function channelFromConversationId(conversationId) {
|
|
4
|
+
const [provider, channel] = conversationId.split(":");
|
|
5
|
+
return provider === "slack" && channel ? channel : void 0;
|
|
6
|
+
}
|
|
7
|
+
function surfaceFromRow(row) {
|
|
8
|
+
if (row.source === "api" || row.source === "scheduler" || row.source === "slack") {
|
|
9
|
+
return row.source;
|
|
10
|
+
}
|
|
11
|
+
if (row.conversationId.startsWith("slack:")) return "slack";
|
|
12
|
+
if (row.conversationId.startsWith("scheduler:")) return "scheduler";
|
|
13
|
+
if (row.conversationId.startsWith("api:")) return "api";
|
|
14
|
+
return "internal";
|
|
15
|
+
}
|
|
16
|
+
function statusFromRow(row) {
|
|
17
|
+
if (row.executionStatus === "failed") return "failed";
|
|
18
|
+
if (row.executionStatus === "idle") return "completed";
|
|
19
|
+
return "active";
|
|
20
|
+
}
|
|
21
|
+
function surfaceLabel(surface) {
|
|
22
|
+
if (surface === "scheduler") return "Scheduler";
|
|
23
|
+
if (surface === "api") return "API";
|
|
24
|
+
if (surface === "internal") return "Internal";
|
|
25
|
+
return "Conversation";
|
|
26
|
+
}
|
|
27
|
+
function slackLocationLabel(args) {
|
|
28
|
+
const channelId = args.channel;
|
|
29
|
+
if (!channelId) return void 0;
|
|
30
|
+
if (args.channelNameRedacted && args.channelName) return args.channelName;
|
|
31
|
+
const name = args.channelName?.replace(/^#/, "");
|
|
32
|
+
if (channelId.startsWith("D")) return "Direct Message";
|
|
33
|
+
if (channelId.startsWith("C")) {
|
|
34
|
+
return name ? `#${name}` : "Public Channel";
|
|
35
|
+
}
|
|
36
|
+
if (channelId.startsWith("G")) {
|
|
37
|
+
if (name?.startsWith("mpdm-")) return "Group DM";
|
|
38
|
+
return "Private Channel";
|
|
39
|
+
}
|
|
40
|
+
return name || channelId;
|
|
41
|
+
}
|
|
42
|
+
function channelNameFromRow(row) {
|
|
43
|
+
if (row.destinationVisibility !== "public") {
|
|
44
|
+
return PRIVATE_CONVERSATION_LABEL;
|
|
45
|
+
}
|
|
46
|
+
return row.channelName ?? void 0;
|
|
47
|
+
}
|
|
48
|
+
function titleFromRow(row, surface) {
|
|
49
|
+
if (row.destinationVisibility !== "public") {
|
|
50
|
+
return PRIVATE_CONVERSATION_LABEL;
|
|
51
|
+
}
|
|
52
|
+
const channel = channelFromConversationId(row.conversationId);
|
|
53
|
+
return row.title ?? slackLocationLabel({
|
|
54
|
+
channel,
|
|
55
|
+
channelName: row.channelName ?? void 0
|
|
56
|
+
}) ?? surfaceLabel(surface);
|
|
57
|
+
}
|
|
58
|
+
function actorFromRow(row) {
|
|
59
|
+
const actor = {
|
|
60
|
+
...row.email ? { email: row.email } : {},
|
|
61
|
+
...row.fullName ? { fullName: row.fullName } : {},
|
|
62
|
+
...row.providerSubjectId ? { slackUserId: row.providerSubjectId } : {},
|
|
63
|
+
...row.handle ? { slackUserName: row.handle } : {}
|
|
64
|
+
};
|
|
65
|
+
return Object.keys(actor).length ? actor : void 0;
|
|
66
|
+
}
|
|
67
|
+
function summaryFromRow(row) {
|
|
68
|
+
const surface = surfaceFromRow(row);
|
|
69
|
+
const channel = channelFromConversationId(row.conversationId);
|
|
70
|
+
const channelName = channelNameFromRow(row);
|
|
71
|
+
const channelNameRedacted = row.destinationVisibility !== "public";
|
|
72
|
+
const actorIdentity = actorFromRow(row);
|
|
73
|
+
return {
|
|
74
|
+
conversationId: row.conversationId,
|
|
75
|
+
cumulativeDurationMs: row.durationMs,
|
|
76
|
+
displayTitle: titleFromRow(row, surface),
|
|
77
|
+
lastProgressAt: new Date(
|
|
78
|
+
row.executionUpdatedAt ?? row.updatedAt
|
|
79
|
+
).toISOString(),
|
|
80
|
+
lastSeenAt: row.lastActivityAt.toISOString(),
|
|
81
|
+
startedAt: row.createdAt.toISOString(),
|
|
82
|
+
status: statusFromRow(row),
|
|
83
|
+
surface,
|
|
84
|
+
...actorIdentity ? { actorIdentity } : {},
|
|
85
|
+
...channel ? { channel } : {},
|
|
86
|
+
...channelName ? { channelName } : {},
|
|
87
|
+
...channelNameRedacted ? { channelNameRedacted: true } : {},
|
|
88
|
+
...row.destinationVisibility === "public" && row.destinationId ? { locationId: row.destinationId } : {}
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export {
|
|
93
|
+
surfaceLabel,
|
|
94
|
+
slackLocationLabel,
|
|
95
|
+
summaryFromRow
|
|
96
|
+
};
|