@sentry/junior 0.193.0 → 0.195.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-DWY3MZZ7.js → agent-hooks-VIBTIP5F.js} +11 -11
- package/dist/api/activity.d.ts +9 -1
- package/dist/api/code/overview.d.ts +12 -0
- package/dist/api/conversations/aggregate.d.ts +2 -0
- package/dist/api/conversations/list.d.ts +1 -1
- package/dist/api/conversations/projection.d.ts +1 -1
- package/dist/api/locations/detail.d.ts +9 -1
- package/dist/api/locations/list.d.ts +5 -0
- package/dist/api/people/code.d.ts +6 -0
- package/dist/api/people/shared.d.ts +9 -1
- package/dist/api/reporting-window.d.ts +39 -1
- package/dist/api/schema/code.d.ts +12 -0
- package/dist/api/schema/conversation.d.ts +28 -3
- package/dist/api/schema/location.d.ts +14 -1
- package/dist/api/schema/person.d.ts +15 -1
- package/dist/api/schema/task.d.ts +83 -8
- package/dist/api/schema.d.ts +2 -2
- package/dist/api/schema.js +3 -1
- package/dist/api.js +320 -222
- package/dist/app.js +108 -39
- package/dist/{catalog-runtime-NAD44W5K.js → catalog-runtime-6E6SGRZK.js} +4 -4
- package/dist/chat/agent/resume.d.ts +2 -0
- package/dist/chat/config.d.ts +2 -0
- package/dist/chat/conversations/history.d.ts +4 -2
- package/dist/chat/event-tasks/store.d.ts +27 -17
- package/dist/chat/resource-events/notification.d.ts +2 -1
- package/dist/chat/services/automated-turn-limit.d.ts +110 -0
- package/dist/chat/services/turn-limit.d.ts +11 -1
- package/dist/chat/slack/automated-turn-limit-notice.d.ts +38 -0
- package/dist/chat/slack/{source-link.d.ts → location-url.d.ts} +1 -1
- package/dist/chat/task-execution/checkpoint.d.ts +2 -0
- package/dist/chat/task-execution/turn-cursor.d.ts +3 -0
- package/dist/chat/tasks/execution-stats.d.ts +15 -2
- package/dist/chat/tasks/read.d.ts +5 -2
- package/dist/chat/usage.d.ts +4 -0
- package/dist/{chunk-GUKGU6R7.js → chunk-3VWIZVK7.js} +1 -1
- package/dist/{chunk-THYNA2QN.js → chunk-5HNXLP4W.js} +1 -1
- package/dist/{chunk-GUMBIDDL.js → chunk-5NR7N567.js} +194 -43
- package/dist/{chunk-N6Q2PNSI.js → chunk-6GGDBXXP.js} +3 -3
- package/dist/{chunk-HMBTX5RK.js → chunk-6TRQLG3D.js} +1 -1
- package/dist/{chunk-IOUUS6H4.js → chunk-7MYXH5LA.js} +1 -1
- package/dist/{chunk-WH5VV2RW.js → chunk-7PQMTME5.js} +1 -1
- package/dist/{chunk-5E5SLAVD.js → chunk-7UED4D5T.js} +23 -25
- package/dist/{chunk-4UA5C7AM.js → chunk-BJZML4RT.js} +8 -8
- package/dist/{chunk-QDU5MW2R.js → chunk-C4NY6L7S.js} +1 -1
- package/dist/{chunk-DVU734PI.js → chunk-CE2P6TOV.js} +3 -3
- package/dist/{chunk-BFP3ZKG6.js → chunk-DTYOEHUP.js} +148 -19
- package/dist/{chunk-S5HS6WRH.js → chunk-FE3Y4KES.js} +5 -5
- package/dist/{chunk-PYBFVK6K.js → chunk-FEZIEEOP.js} +985 -569
- package/dist/{chunk-5S6AQFNG.js → chunk-FPQPYJEG.js} +23 -29
- package/dist/{chunk-42N6CDWF.js → chunk-HE5PZAPS.js} +4 -4
- package/dist/{chunk-QY2IU47O.js → chunk-HUQOXMDG.js} +1 -1
- package/dist/{chunk-IQCL5JGL.js → chunk-I4RH3KLJ.js} +1 -1
- package/dist/{chunk-LXRTHE43.js → chunk-JBSCMOLR.js} +5 -5
- package/dist/{chunk-OICYQPKP.js → chunk-KBPWC7NU.js} +1 -1
- package/dist/{chunk-2CYWEVOP.js → chunk-KQ3GZGBK.js} +88 -68
- package/dist/{chunk-GTXQHZ2O.js → chunk-KUQRWV53.js} +5 -5
- package/dist/{chunk-IBXXTO3J.js → chunk-L62JVQPL.js} +3 -3
- package/dist/{chunk-KWXZMHJS.js → chunk-LM7UE523.js} +3 -3
- package/dist/{chunk-WJJDQLVL.js → chunk-LMYRF6HX.js} +6 -2
- package/dist/{chunk-AZVDODSP.js → chunk-N67T4VY3.js} +9 -9
- package/dist/{chunk-D4XQZOHB.js → chunk-OQHO62VA.js} +8 -8
- package/dist/{chunk-FQ5HFSFR.js → chunk-PFQRZ4IB.js} +9 -6
- package/dist/{chunk-LG7Q4OW4.js → chunk-PYTRZZ4V.js} +8 -8
- package/dist/{chunk-THFNL3TL.js → chunk-QHJZSYKY.js} +2 -2
- package/dist/{chunk-5LEVZYXF.js → chunk-QKHZF2LH.js} +4 -4
- package/dist/{chunk-EYIMZY5O.js → chunk-QPZL2IYT.js} +100 -9
- package/dist/{chunk-D5YQPCEG.js → chunk-R5BGW4WR.js} +24 -2
- package/dist/{chunk-COCVPDWX.js → chunk-R5OHONYU.js} +6 -6
- package/dist/{chunk-DXFUYLHX.js → chunk-RKA22BQP.js} +1 -1
- package/dist/{chunk-3YZ2Q6AW.js → chunk-RQO67SAO.js} +2 -2
- package/dist/{chunk-ZFPEPWOO.js → chunk-RZ3PBNDV.js} +60 -29
- package/dist/{chunk-K47OVEO4.js → chunk-VYDIA2UL.js} +1 -1
- package/dist/{chunk-QWY4KI2V.js → chunk-X3PBQ4BK.js} +1 -1
- package/dist/cli/chat.js +33 -33
- package/dist/cli/check.js +5 -5
- package/dist/cli/plugins.js +12 -12
- package/dist/cli/snapshot-create.js +9 -9
- package/dist/cli/upgrade.js +6 -6
- package/dist/db/schema/event-tasks.d.ts +21 -0
- package/dist/db/schema.d.ts +19 -0
- package/dist/{db-H5MDRQEY.js → db-FVCSDROR.js} +6 -6
- package/dist/instrumentation.js +3 -3
- package/dist/nitro.js +6 -6
- package/dist/{oauth-callback-server-IOU3NUHT.js → oauth-callback-server-Z5PXTDOE.js} +29 -29
- package/dist/{runner-FZ5ZHLFG.js → runner-RHYU7OGV.js} +21 -21
- package/dist/{skills-AR3WD6BX.js → skills-QTN73DN5.js} +5 -5
- package/dist/spawn-R56OWLUH.js +42 -0
- package/dist/task-runner-LLJZTLRP.js +36 -0
- package/dist/{validation-VYE7TQY7.js → validation-2ZK7GA6N.js} +5 -5
- package/dist/version.js +1 -1
- package/dist/{work-CTQFWYKE.js → work-7IBKSZRU.js} +21 -21
- package/dist/{worker-6WQU3IT5.js → worker-RNVQVCO7.js} +10 -10
- package/migrations/0038_event_task_status.sql +5 -0
- package/migrations/meta/0038_snapshot.json +3323 -0
- package/migrations/meta/_journal.json +8 -1
- package/package.json +4 -4
- package/dist/spawn-ZU6JABR7.js +0 -42
- package/dist/task-runner-EEGGG2PM.js +0 -36
package/dist/api.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DAY_MS,
|
|
3
3
|
HOUR_MS,
|
|
4
|
+
WINDOW_SEVEN_DAY_HOURS,
|
|
4
5
|
acceptedConversationMessageSchema,
|
|
5
6
|
activityDays,
|
|
6
7
|
activityHours,
|
|
8
|
+
activitySixHours,
|
|
7
9
|
actorDirectoryReportSchema,
|
|
8
10
|
actorProfileReportSchema,
|
|
9
11
|
apiErrorSchema,
|
|
@@ -31,6 +33,7 @@ import {
|
|
|
31
33
|
deleteWorkspaceResponseSchema,
|
|
32
34
|
fillUtcDays,
|
|
33
35
|
fillUtcHours,
|
|
36
|
+
fillUtcSixHours,
|
|
34
37
|
locationDetailReportSchema,
|
|
35
38
|
locationDirectoryReportSchema,
|
|
36
39
|
locationParamsSchema,
|
|
@@ -39,20 +42,23 @@ import {
|
|
|
39
42
|
personalTokenListSchema,
|
|
40
43
|
personalTokenParamsSchema,
|
|
41
44
|
revokePersonalTokenResponseSchema,
|
|
45
|
+
startOfUtcHour,
|
|
42
46
|
statsReportSchema,
|
|
47
|
+
sumUtcHoursIntoSixHours,
|
|
43
48
|
taskExecutionListSchema,
|
|
44
49
|
taskListSchema,
|
|
45
50
|
taskParamsSchema,
|
|
46
51
|
taskRunListSchema,
|
|
47
52
|
trailingUtcDayWindow,
|
|
48
53
|
trailingUtcHourWindow,
|
|
54
|
+
trailingUtcSixHourWindow,
|
|
49
55
|
utcDayKey,
|
|
50
56
|
utcHourKey,
|
|
51
57
|
workspaceBodySchema,
|
|
52
58
|
workspaceListSchema,
|
|
53
59
|
workspaceParamsSchema,
|
|
54
60
|
workspaceSchema
|
|
55
|
-
} from "./chunk-
|
|
61
|
+
} from "./chunk-QPZL2IYT.js";
|
|
56
62
|
import {
|
|
57
63
|
appendAndEnqueueWebMessage,
|
|
58
64
|
conversationArchiveTimes,
|
|
@@ -72,13 +78,17 @@ import {
|
|
|
72
78
|
resolveSlackConversationContextFromThreadId,
|
|
73
79
|
viewerConversationMembership,
|
|
74
80
|
webActorFromEmail
|
|
75
|
-
} from "./chunk-
|
|
81
|
+
} from "./chunk-PYTRZZ4V.js";
|
|
76
82
|
import {
|
|
77
83
|
buildSentryConversationUrl,
|
|
78
84
|
buildSentryEventUrl,
|
|
79
85
|
getWebAuthorization
|
|
80
|
-
} from "./chunk-
|
|
86
|
+
} from "./chunk-5HNXLP4W.js";
|
|
81
87
|
import {
|
|
88
|
+
conversationActiveDaysColumn,
|
|
89
|
+
conversationAggregateColumns,
|
|
90
|
+
conversationRangeColumns,
|
|
91
|
+
emptyTaskRunWindows,
|
|
82
92
|
readTaskExecutionByConversationId,
|
|
83
93
|
readTaskExecutionDays,
|
|
84
94
|
readTaskExecutionHours,
|
|
@@ -87,7 +97,7 @@ import {
|
|
|
87
97
|
readTaskExecutionSummaries,
|
|
88
98
|
readTaskExecutions,
|
|
89
99
|
readTaskRuns
|
|
90
|
-
} from "./chunk-
|
|
100
|
+
} from "./chunk-5NR7N567.js";
|
|
91
101
|
import {
|
|
92
102
|
healthReportSchema,
|
|
93
103
|
pluginOperationalReportFeedSchema,
|
|
@@ -102,6 +112,7 @@ import {
|
|
|
102
112
|
getEventTask,
|
|
103
113
|
getResourceEventCatalog,
|
|
104
114
|
isListedScheduledTask,
|
|
115
|
+
listDeletedEventTasksCreatedBy,
|
|
105
116
|
listEventTasksCreatedBy,
|
|
106
117
|
listPublicEventTasksForTeams,
|
|
107
118
|
listPublicScheduledTasksForTeams,
|
|
@@ -110,24 +121,24 @@ import {
|
|
|
110
121
|
readScheduledTask,
|
|
111
122
|
readStats,
|
|
112
123
|
saveScheduledTask
|
|
113
|
-
} from "./chunk-
|
|
124
|
+
} from "./chunk-DTYOEHUP.js";
|
|
114
125
|
import {
|
|
115
126
|
parseSlackThreadId
|
|
116
|
-
} from "./chunk-
|
|
127
|
+
} from "./chunk-6TRQLG3D.js";
|
|
117
128
|
import {
|
|
118
129
|
cancelHumanFacingPendingMessages,
|
|
119
130
|
getConversation
|
|
120
|
-
} from "./chunk-
|
|
131
|
+
} from "./chunk-QKHZF2LH.js";
|
|
121
132
|
import "./chunk-DA2KGZZI.js";
|
|
122
133
|
import {
|
|
123
134
|
agentTurnUsageSchema,
|
|
124
135
|
fallbackShortTitle,
|
|
125
136
|
hasAgentTurnUsage,
|
|
126
137
|
renderJuniorNativeConversationEvent
|
|
127
|
-
} from "./chunk-
|
|
138
|
+
} from "./chunk-R5BGW4WR.js";
|
|
128
139
|
import {
|
|
129
140
|
getCachedSnapshot
|
|
130
|
-
} from "./chunk-
|
|
141
|
+
} from "./chunk-L62JVQPL.js";
|
|
131
142
|
import "./chunk-PDO5BLNM.js";
|
|
132
143
|
import {
|
|
133
144
|
getVercelConversationWorkQueue
|
|
@@ -153,7 +164,7 @@ import {
|
|
|
153
164
|
updateWorkspace,
|
|
154
165
|
withSlackRetries,
|
|
155
166
|
workspaceRepoCheckoutPath
|
|
156
|
-
} from "./chunk-
|
|
167
|
+
} from "./chunk-PFQRZ4IB.js";
|
|
157
168
|
import "./chunk-3Y47VMHV.js";
|
|
158
169
|
import {
|
|
159
170
|
getConversationStore,
|
|
@@ -162,7 +173,7 @@ import {
|
|
|
162
173
|
locationFromRow,
|
|
163
174
|
parseSessionSource,
|
|
164
175
|
resolveRootConversationId
|
|
165
|
-
} from "./chunk-
|
|
176
|
+
} from "./chunk-KQ3GZGBK.js";
|
|
166
177
|
import {
|
|
167
178
|
conversationReadColumns,
|
|
168
179
|
juniorApiTokens,
|
|
@@ -174,23 +185,23 @@ import {
|
|
|
174
185
|
juniorIdentities,
|
|
175
186
|
juniorSchedulerTasks,
|
|
176
187
|
juniorUsers
|
|
177
|
-
} from "./chunk-
|
|
188
|
+
} from "./chunk-FPQPYJEG.js";
|
|
178
189
|
import {
|
|
179
190
|
create,
|
|
180
191
|
hash
|
|
181
|
-
} from "./chunk-
|
|
182
|
-
import "./chunk-
|
|
192
|
+
} from "./chunk-LM7UE523.js";
|
|
193
|
+
import "./chunk-7MYXH5LA.js";
|
|
183
194
|
import {
|
|
184
195
|
decodeStoredConversationEvent
|
|
185
196
|
} from "./chunk-GFBR4S3Q.js";
|
|
186
197
|
import {
|
|
187
198
|
juniorDestinations
|
|
188
199
|
} from "./chunk-VFUK3X5B.js";
|
|
189
|
-
import "./chunk-
|
|
200
|
+
import "./chunk-LMYRF6HX.js";
|
|
190
201
|
import "./chunk-D4YV5TDV.js";
|
|
191
|
-
import "./chunk-
|
|
192
|
-
import "./chunk-
|
|
193
|
-
import "./chunk-
|
|
202
|
+
import "./chunk-KBPWC7NU.js";
|
|
203
|
+
import "./chunk-RKA22BQP.js";
|
|
204
|
+
import "./chunk-X3PBQ4BK.js";
|
|
194
205
|
import "./chunk-CEMMLV5L.js";
|
|
195
206
|
import {
|
|
196
207
|
parseSlackChannelId,
|
|
@@ -202,9 +213,9 @@ import "./chunk-TXKUKMVO.js";
|
|
|
202
213
|
import {
|
|
203
214
|
logException,
|
|
204
215
|
logWarn
|
|
205
|
-
} from "./chunk-
|
|
216
|
+
} from "./chunk-HUQOXMDG.js";
|
|
206
217
|
import "./chunk-PEQXYSSE.js";
|
|
207
|
-
import "./chunk-
|
|
218
|
+
import "./chunk-C4NY6L7S.js";
|
|
208
219
|
|
|
209
220
|
// src/api.ts
|
|
210
221
|
import { Hono as Hono9 } from "hono";
|
|
@@ -450,7 +461,7 @@ async function appendConversationMessageForViewer(viewer, conversationId, body)
|
|
|
450
461
|
}
|
|
451
462
|
}
|
|
452
463
|
|
|
453
|
-
// src/chat/slack/
|
|
464
|
+
// src/chat/slack/location-url.ts
|
|
454
465
|
function parseSlackTeamDomain(value) {
|
|
455
466
|
if (typeof value !== "string") return void 0;
|
|
456
467
|
const domain = value.trim().toLowerCase();
|
|
@@ -463,7 +474,7 @@ function archivePathFromThreadTs(threadTs) {
|
|
|
463
474
|
const [seconds, fraction = ""] = threadTs.split(".");
|
|
464
475
|
return `p${seconds}${(fraction ?? "").padEnd(6, "0").slice(0, 6)}`;
|
|
465
476
|
}
|
|
466
|
-
function
|
|
477
|
+
function buildSlackLocationUrl(args) {
|
|
467
478
|
const channelId = parseSlackChannelId(args.channelId);
|
|
468
479
|
const teamDomain = parseSlackTeamDomain(args.teamDomain);
|
|
469
480
|
const threadTs = parseSlackMessageTs(args.threadTs);
|
|
@@ -1305,18 +1316,16 @@ function surfaceFromSource(source, conversationId) {
|
|
|
1305
1316
|
}
|
|
1306
1317
|
return surfaceFromConversationId(conversationId);
|
|
1307
1318
|
}
|
|
1308
|
-
function
|
|
1319
|
+
function locationUrlFromConversation(args) {
|
|
1309
1320
|
const { conversation } = args;
|
|
1310
|
-
if (!args.canViewPrivateContent || conversation.
|
|
1321
|
+
if (!args.canViewPrivateContent || conversation.location?.provider !== "slack") {
|
|
1311
1322
|
return void 0;
|
|
1312
1323
|
}
|
|
1313
|
-
const teamDomain = args.teamDomainByTeamId?.get(
|
|
1314
|
-
|
|
1315
|
-
);
|
|
1316
|
-
const threadTs = conversation.sessionSource.threadTs;
|
|
1324
|
+
const teamDomain = args.teamDomainByTeamId?.get(conversation.location.teamId);
|
|
1325
|
+
const threadTs = conversation.location.threadTs;
|
|
1317
1326
|
if (!teamDomain || !threadTs) return void 0;
|
|
1318
|
-
return
|
|
1319
|
-
channelId: conversation.
|
|
1327
|
+
return buildSlackLocationUrl({
|
|
1328
|
+
channelId: conversation.location.channelId,
|
|
1320
1329
|
teamDomain,
|
|
1321
1330
|
threadTs
|
|
1322
1331
|
});
|
|
@@ -1397,7 +1406,7 @@ function conversationSummaryFromStoredConversation(args) {
|
|
|
1397
1406
|
conversation.conversationId
|
|
1398
1407
|
);
|
|
1399
1408
|
const actorIdentity = actorIdentityReport(conversation.actor);
|
|
1400
|
-
const
|
|
1409
|
+
const locationUrl = locationUrlFromConversation({
|
|
1401
1410
|
canViewPrivateContent,
|
|
1402
1411
|
conversation,
|
|
1403
1412
|
...args.teamDomainByTeamId ? { teamDomainByTeamId: args.teamDomainByTeamId } : void 0
|
|
@@ -1433,7 +1442,7 @@ function conversationSummaryFromStoredConversation(args) {
|
|
|
1433
1442
|
...args.auxiliaryCosts ? { auxiliaryCosts: args.auxiliaryCosts } : void 0,
|
|
1434
1443
|
...usage3 ? { cumulativeUsage: usage3 } : void 0,
|
|
1435
1444
|
...actorIdentity ? { actorIdentity } : void 0,
|
|
1436
|
-
...
|
|
1445
|
+
...locationUrl ? { locationUrl } : void 0,
|
|
1437
1446
|
archivedAt: args.archivedAtMs === void 0 ? null : new Date(args.archivedAtMs).toISOString(),
|
|
1438
1447
|
...slackThread ? { channel: slackThread.channelId } : void 0,
|
|
1439
1448
|
...channelName ? { channelName } : void 0,
|
|
@@ -1838,7 +1847,7 @@ function conversationFeedMembershipFilter(status, filter) {
|
|
|
1838
1847
|
async function conversationRows(db, limit, status, filter) {
|
|
1839
1848
|
return db.select({
|
|
1840
1849
|
conversation: conversationReadColumns(),
|
|
1841
|
-
|
|
1850
|
+
location: juniorDestinations,
|
|
1842
1851
|
identityDisplayName: juniorIdentities.displayName,
|
|
1843
1852
|
identityEmail: juniorIdentities.email,
|
|
1844
1853
|
identityHandle: juniorIdentities.handle,
|
|
@@ -1864,9 +1873,9 @@ async function conversationRows(db, limit, status, filter) {
|
|
|
1864
1873
|
}
|
|
1865
1874
|
function conversationFromRow(row) {
|
|
1866
1875
|
const value = row.conversation;
|
|
1867
|
-
const
|
|
1868
|
-
if (value.sessionSource !== null && !
|
|
1869
|
-
throw new Error("Conversation
|
|
1876
|
+
const legacySessionSource = value.sessionSource === null ? void 0 : parseSessionSource(value.sessionSource);
|
|
1877
|
+
if (value.sessionSource !== null && !legacySessionSource) {
|
|
1878
|
+
throw new Error("Conversation legacy source_json is invalid");
|
|
1870
1879
|
}
|
|
1871
1880
|
const actorFullName = row.userDisplayName?.trim() ? row.userDisplayName : row.identityDisplayName;
|
|
1872
1881
|
const actor = row.identityProvider === "slack" ? {
|
|
@@ -1879,8 +1888,8 @@ function conversationFromRow(row) {
|
|
|
1879
1888
|
} : void 0;
|
|
1880
1889
|
const location = locationFromRow(
|
|
1881
1890
|
value.location,
|
|
1882
|
-
row.
|
|
1883
|
-
|
|
1891
|
+
row.location,
|
|
1892
|
+
legacySessionSource
|
|
1884
1893
|
);
|
|
1885
1894
|
return {
|
|
1886
1895
|
schemaVersion: 1,
|
|
@@ -1897,7 +1906,6 @@ function conversationFromRow(row) {
|
|
|
1897
1906
|
...location ? { location } : void 0,
|
|
1898
1907
|
...value.channelName ? { channelName: value.channelName } : void 0,
|
|
1899
1908
|
...value.source ? { source: value.source } : void 0,
|
|
1900
|
-
...sessionSource ? { sessionSource } : void 0,
|
|
1901
1909
|
...value.title ? { title: value.title } : void 0,
|
|
1902
1910
|
...value.transcriptPurgedAt ? { transcriptPurgedAtMs: value.transcriptPurgedAt.getTime() } : void 0
|
|
1903
1911
|
};
|
|
@@ -1906,7 +1914,7 @@ async function readConversationRecordFromSql(conversationId) {
|
|
|
1906
1914
|
const db = getDb();
|
|
1907
1915
|
const rows = await db.select({
|
|
1908
1916
|
conversation: conversationReadColumns(),
|
|
1909
|
-
|
|
1917
|
+
location: juniorDestinations,
|
|
1910
1918
|
identityDisplayName: juniorIdentities.displayName,
|
|
1911
1919
|
identityEmail: juniorIdentities.email,
|
|
1912
1920
|
identityHandle: juniorIdentities.handle,
|
|
@@ -1925,7 +1933,7 @@ async function readConversationRecordFromSql(conversationId) {
|
|
|
1925
1933
|
return row ? {
|
|
1926
1934
|
conversation: conversationFromRow(row),
|
|
1927
1935
|
durationMs: row.conversation.durationMs,
|
|
1928
|
-
...row.
|
|
1936
|
+
...row.location?.visibility === "public" ? { locationId: row.location.id } : void 0,
|
|
1929
1937
|
usage: row.conversation.usage,
|
|
1930
1938
|
rootConversationId: row.conversation.rootConversationId
|
|
1931
1939
|
} : void 0;
|
|
@@ -1982,7 +1990,7 @@ async function readConversationFeedFromSql(options = {}) {
|
|
|
1982
1990
|
readRootConversationMetricsFromSql(db, conversationIds),
|
|
1983
1991
|
resolveSlackTeamDomains(
|
|
1984
1992
|
conversations.flatMap(
|
|
1985
|
-
(conversation) => conversation.
|
|
1993
|
+
(conversation) => conversation.location?.provider === "slack" ? [conversation.location.teamId] : []
|
|
1986
1994
|
)
|
|
1987
1995
|
),
|
|
1988
1996
|
listConversationWork(conversationIds),
|
|
@@ -2015,7 +2023,7 @@ async function readConversationFeedFromSql(options = {}) {
|
|
|
2015
2023
|
auxiliaryCosts: auxiliaryCostsByRoot.get(conversation.conversationId),
|
|
2016
2024
|
durationMs: metrics?.durationMs ?? row.conversation.durationMs,
|
|
2017
2025
|
teamDomainByTeamId,
|
|
2018
|
-
...row.
|
|
2026
|
+
...row.location?.visibility === "public" ? { locationId: row.location.id } : void 0,
|
|
2019
2027
|
usage: metrics?.usage ?? row.conversation.usage ?? void 0
|
|
2020
2028
|
});
|
|
2021
2029
|
const work = {
|
|
@@ -2056,7 +2064,7 @@ async function readConversationFeed(options = {}) {
|
|
|
2056
2064
|
}
|
|
2057
2065
|
|
|
2058
2066
|
// src/chat/tasks/read.ts
|
|
2059
|
-
import { and as and9, eq as eq9, or as or4 } from "drizzle-orm";
|
|
2067
|
+
import { and as and9, desc as desc4, eq as eq9, inArray as inArray6, or as or4 } from "drizzle-orm";
|
|
2060
2068
|
|
|
2061
2069
|
// src/chat/scheduled-tasks/personal.ts
|
|
2062
2070
|
import { and as and8, desc as desc3, eq as eq8, inArray as inArray5, lt as lt2, notInArray, or as or3, sql as sql8 } from "drizzle-orm";
|
|
@@ -2274,7 +2282,7 @@ function executionSummaryFields(stats) {
|
|
|
2274
2282
|
return {
|
|
2275
2283
|
...stats?.lastConversationId ? { lastConversationId: stats.lastConversationId } : void 0,
|
|
2276
2284
|
...stats?.lastExecutedAtMs ? { lastRunAt: new Date(stats.lastExecutedAtMs).toISOString() } : void 0,
|
|
2277
|
-
|
|
2285
|
+
runs: stats?.runs ?? emptyTaskRunWindows(),
|
|
2278
2286
|
totalRuns: stats?.totalRuns ?? 0
|
|
2279
2287
|
};
|
|
2280
2288
|
}
|
|
@@ -2359,7 +2367,7 @@ async function resolveViewerTaskCandidate(user, kind, id) {
|
|
|
2359
2367
|
};
|
|
2360
2368
|
}
|
|
2361
2369
|
const task = await getEventTask(db, id);
|
|
2362
|
-
if (!task) return void 0;
|
|
2370
|
+
if (!task || task.status === "deleted") return void 0;
|
|
2363
2371
|
const ownedByViewer = eventTaskBelongsToUser(task, user);
|
|
2364
2372
|
const destinations = await destinationDetails([task.destination]);
|
|
2365
2373
|
const destination = destinations.get(destinationKey(task.destination));
|
|
@@ -2407,6 +2415,26 @@ async function taskSummaryForCandidate(candidate) {
|
|
|
2407
2415
|
createdByEmail
|
|
2408
2416
|
);
|
|
2409
2417
|
}
|
|
2418
|
+
function emptyTaskExecutionDay(date) {
|
|
2419
|
+
return { costUsd: 0, date, event: 0, scheduled: 0 };
|
|
2420
|
+
}
|
|
2421
|
+
function emptyTaskExecutionStatusDay(date) {
|
|
2422
|
+
return { blocked: 0, completed: 0, date, failed: 0 };
|
|
2423
|
+
}
|
|
2424
|
+
function taskExecutionSixHours(hours, nowMs = Date.now()) {
|
|
2425
|
+
return sumUtcHoursIntoSixHours({
|
|
2426
|
+
empty: emptyTaskExecutionDay,
|
|
2427
|
+
hours,
|
|
2428
|
+
nowMs
|
|
2429
|
+
});
|
|
2430
|
+
}
|
|
2431
|
+
function taskExecutionStatusSixHours(hours, nowMs = Date.now()) {
|
|
2432
|
+
return sumUtcHoursIntoSixHours({
|
|
2433
|
+
empty: emptyTaskExecutionStatusDay,
|
|
2434
|
+
hours,
|
|
2435
|
+
nowMs
|
|
2436
|
+
});
|
|
2437
|
+
}
|
|
2410
2438
|
async function readViewerTasks(user) {
|
|
2411
2439
|
const db = getDb();
|
|
2412
2440
|
const identityIds = new Set(user.identities.map((identity) => identity.id));
|
|
@@ -2498,26 +2526,94 @@ async function readViewerTasks(user) {
|
|
|
2498
2526
|
return {
|
|
2499
2527
|
executionDays,
|
|
2500
2528
|
executionHours,
|
|
2529
|
+
executionSixHours: taskExecutionSixHours(executionHours),
|
|
2501
2530
|
tasks,
|
|
2502
2531
|
truncated: ownedCandidates.length > TASK_LIST_LIMIT || publicCandidates.length > TASK_LIST_LIMIT
|
|
2503
2532
|
};
|
|
2504
2533
|
}
|
|
2505
|
-
async function
|
|
2506
|
-
const
|
|
2507
|
-
|
|
2508
|
-
|
|
2534
|
+
async function readDeletedOwnedScheduledTasks(user) {
|
|
2535
|
+
const identityIds = user.identities.map((identity) => identity.id);
|
|
2536
|
+
if (identityIds.length === 0) return [];
|
|
2537
|
+
const rows = await getDb().select({
|
|
2538
|
+
creatorIdentityId: juniorSchedulerTasks.creatorIdentityId,
|
|
2539
|
+
id: juniorSchedulerTasks.id,
|
|
2540
|
+
record: juniorSchedulerTasks.record,
|
|
2541
|
+
title: juniorSchedulerTasks.title
|
|
2542
|
+
}).from(juniorSchedulerTasks).where(
|
|
2543
|
+
and9(
|
|
2544
|
+
eq9(juniorSchedulerTasks.status, "deleted"),
|
|
2545
|
+
inArray6(juniorSchedulerTasks.creatorIdentityId, identityIds)
|
|
2546
|
+
)
|
|
2547
|
+
).orderBy(
|
|
2548
|
+
desc4(juniorSchedulerTasks.createdAtMs),
|
|
2549
|
+
desc4(juniorSchedulerTasks.id)
|
|
2550
|
+
).limit(TASK_EXECUTION_LIST_LIMIT);
|
|
2551
|
+
return rows.map(parseScheduledTaskRow).filter((task) => task?.status === "deleted");
|
|
2552
|
+
}
|
|
2553
|
+
async function readDeletedOwnedEventTasks(user) {
|
|
2554
|
+
return await listDeletedEventTasksCreatedBy(
|
|
2555
|
+
getDb(),
|
|
2556
|
+
user,
|
|
2557
|
+
TASK_EXECUTION_LIST_LIMIT
|
|
2509
2558
|
);
|
|
2559
|
+
}
|
|
2560
|
+
function taskTitleForRun(run, taskTitles) {
|
|
2561
|
+
return taskTitles.get(`${run.kind}:${run.taskId}`) ?? run.title?.trim() ?? "Untitled task";
|
|
2562
|
+
}
|
|
2563
|
+
function addDeletedTaskRun(args, taskTitles, tasks) {
|
|
2564
|
+
const key = `${args.kind}:${args.taskId}`;
|
|
2565
|
+
if (taskTitles.has(key)) return;
|
|
2566
|
+
taskTitles.set(key, args.title);
|
|
2567
|
+
tasks.push({ kind: args.kind, taskId: args.taskId });
|
|
2568
|
+
}
|
|
2569
|
+
async function readViewerTaskRuns(user) {
|
|
2570
|
+
const [taskList, deletedScheduled, deletedEvent] = await Promise.all([
|
|
2571
|
+
readViewerTasks(user),
|
|
2572
|
+
readDeletedOwnedScheduledTasks(user),
|
|
2573
|
+
readDeletedOwnedEventTasks(user)
|
|
2574
|
+
]);
|
|
2575
|
+
const taskTitles = /* @__PURE__ */ new Map();
|
|
2576
|
+
const tasks = [];
|
|
2577
|
+
for (const task of taskList.tasks) {
|
|
2578
|
+
taskTitles.set(`${task.kind}:${task.id}`, task.title);
|
|
2579
|
+
tasks.push({ kind: task.kind, taskId: task.id });
|
|
2580
|
+
}
|
|
2581
|
+
for (const task of deletedScheduled) {
|
|
2582
|
+
const instruction = displayText(task.task.text, "Untitled scheduled task");
|
|
2583
|
+
addDeletedTaskRun(
|
|
2584
|
+
{
|
|
2585
|
+
kind: "scheduled",
|
|
2586
|
+
taskId: task.id,
|
|
2587
|
+
title: taskDisplayTitle(
|
|
2588
|
+
task.title,
|
|
2589
|
+
instruction,
|
|
2590
|
+
"Untitled scheduled task"
|
|
2591
|
+
)
|
|
2592
|
+
},
|
|
2593
|
+
taskTitles,
|
|
2594
|
+
tasks
|
|
2595
|
+
);
|
|
2596
|
+
}
|
|
2597
|
+
for (const task of deletedEvent) {
|
|
2598
|
+
const instruction = displayText(task.task.text, "Untitled event task");
|
|
2599
|
+
addDeletedTaskRun(
|
|
2600
|
+
{
|
|
2601
|
+
kind: "event",
|
|
2602
|
+
taskId: task.id,
|
|
2603
|
+
title: taskDisplayTitle(task.title, instruction, "Untitled event task")
|
|
2604
|
+
},
|
|
2605
|
+
taskTitles,
|
|
2606
|
+
tasks
|
|
2607
|
+
);
|
|
2608
|
+
}
|
|
2510
2609
|
const runs = await readTaskRuns({
|
|
2511
2610
|
limit: TASK_EXECUTION_LIST_LIMIT + 1,
|
|
2512
|
-
tasks
|
|
2513
|
-
kind: task.kind,
|
|
2514
|
-
taskId: task.id
|
|
2515
|
-
}))
|
|
2611
|
+
tasks
|
|
2516
2612
|
});
|
|
2517
2613
|
return {
|
|
2518
2614
|
runs: runs.slice(0, TASK_EXECUTION_LIST_LIMIT).map((run) => ({
|
|
2519
2615
|
...run,
|
|
2520
|
-
taskTitle:
|
|
2616
|
+
taskTitle: taskTitleForRun(run, taskTitles)
|
|
2521
2617
|
})),
|
|
2522
2618
|
truncated: runs.length > TASK_EXECUTION_LIST_LIMIT
|
|
2523
2619
|
};
|
|
@@ -2550,6 +2646,7 @@ async function readViewerTaskExecutions(user, kind, id) {
|
|
|
2550
2646
|
return {
|
|
2551
2647
|
executionDays,
|
|
2552
2648
|
executionHours,
|
|
2649
|
+
executionSixHours: taskExecutionStatusSixHours(executionHours),
|
|
2553
2650
|
executions: executions.slice(0, TASK_EXECUTION_LIST_LIMIT),
|
|
2554
2651
|
task,
|
|
2555
2652
|
truncated: executions.length > TASK_EXECUTION_LIST_LIMIT
|
|
@@ -2611,7 +2708,7 @@ async function deleteViewerTask(user, kind, id) {
|
|
|
2611
2708
|
}
|
|
2612
2709
|
}
|
|
2613
2710
|
const task = await getEventTask(getDb(), id);
|
|
2614
|
-
if (!task || !eventTaskBelongsToUser(task, user)) {
|
|
2711
|
+
if (!task || task.status === "deleted" || !eventTaskBelongsToUser(task, user)) {
|
|
2615
2712
|
throw new ViewerTaskNotFoundError();
|
|
2616
2713
|
}
|
|
2617
2714
|
await deleteEventTask(getDb(), id);
|
|
@@ -2687,7 +2784,7 @@ async function readConversationDetailFromSql(conversationId, options) {
|
|
|
2687
2784
|
...options.viewer ? { viewer: options.viewer } : void 0
|
|
2688
2785
|
}),
|
|
2689
2786
|
resolveSlackTeamDomains(
|
|
2690
|
-
record.conversation.
|
|
2787
|
+
record.conversation.location?.provider === "slack" ? [record.conversation.location.teamId] : []
|
|
2691
2788
|
)
|
|
2692
2789
|
]);
|
|
2693
2790
|
const access = accessByConversation.get(conversationId);
|
|
@@ -2934,90 +3031,8 @@ async function requireConversationPendingMessages(conversationId, options = {})
|
|
|
2934
3031
|
}
|
|
2935
3032
|
|
|
2936
3033
|
// src/api/conversations/stats.query.ts
|
|
2937
|
-
import { and as and10, eq as eq10, gte, isNull as isNull4, lte, sql as
|
|
3034
|
+
import { and as and10, eq as eq10, gte, isNull as isNull4, lte, sql as sql9 } from "drizzle-orm";
|
|
2938
3035
|
import { alias as alias3 } from "drizzle-orm/pg-core";
|
|
2939
|
-
|
|
2940
|
-
// src/api/conversations/aggregate.ts
|
|
2941
|
-
import { sql as sql9 } from "drizzle-orm";
|
|
2942
|
-
function usageTokenValue(source, field) {
|
|
2943
|
-
return sql9`CASE
|
|
2944
|
-
WHEN ${source.usage}->>${field} IS NOT NULL
|
|
2945
|
-
THEN (${source.usage}->>${field})::double precision
|
|
2946
|
-
ELSE NULL
|
|
2947
|
-
END`;
|
|
2948
|
-
}
|
|
2949
|
-
function tokenValue(source) {
|
|
2950
|
-
return sql9`
|
|
2951
|
-
CASE
|
|
2952
|
-
WHEN COALESCE(
|
|
2953
|
-
${source.usage}->>'inputTokens',
|
|
2954
|
-
${source.usage}->>'outputTokens',
|
|
2955
|
-
${source.usage}->>'cachedInputTokens',
|
|
2956
|
-
${source.usage}->>'cacheCreationTokens'
|
|
2957
|
-
) IS NOT NULL
|
|
2958
|
-
THEN COALESCE((${source.usage}->>'inputTokens')::double precision, 0)
|
|
2959
|
-
+ COALESCE((${source.usage}->>'outputTokens')::double precision, 0)
|
|
2960
|
-
+ COALESCE((${source.usage}->>'cachedInputTokens')::double precision, 0)
|
|
2961
|
-
+ COALESCE((${source.usage}->>'cacheCreationTokens')::double precision, 0)
|
|
2962
|
-
WHEN ${source.usage}->>'totalTokens' IS NOT NULL
|
|
2963
|
-
THEN (${source.usage}->>'totalTokens')::double precision
|
|
2964
|
-
ELSE NULL
|
|
2965
|
-
END
|
|
2966
|
-
`;
|
|
2967
|
-
}
|
|
2968
|
-
function costValue(source) {
|
|
2969
|
-
return sql9`
|
|
2970
|
-
CASE
|
|
2971
|
-
WHEN ${source.usage}->'cost'->>'total' IS NOT NULL
|
|
2972
|
-
THEN (${source.usage}->'cost'->>'total')::double precision
|
|
2973
|
-
WHEN COALESCE(
|
|
2974
|
-
${source.usage}->'cost'->>'input',
|
|
2975
|
-
${source.usage}->'cost'->>'output',
|
|
2976
|
-
${source.usage}->'cost'->>'cacheRead',
|
|
2977
|
-
${source.usage}->'cost'->>'cacheWrite'
|
|
2978
|
-
) IS NOT NULL
|
|
2979
|
-
THEN COALESCE((${source.usage}->'cost'->>'input')::double precision, 0)
|
|
2980
|
-
+ COALESCE((${source.usage}->'cost'->>'output')::double precision, 0)
|
|
2981
|
-
+ COALESCE((${source.usage}->'cost'->>'cacheRead')::double precision, 0)
|
|
2982
|
-
+ COALESCE((${source.usage}->'cost'->>'cacheWrite')::double precision, 0)
|
|
2983
|
-
ELSE NULL
|
|
2984
|
-
END
|
|
2985
|
-
`;
|
|
2986
|
-
}
|
|
2987
|
-
function conversationAggregateColumns(sources) {
|
|
2988
|
-
const metrics = sources?.metrics ?? juniorConversations;
|
|
2989
|
-
const roots = sources?.roots ?? juniorConversations;
|
|
2990
|
-
const conversationCount = sources ? sql9`COUNT(DISTINCT ${roots.conversationId})` : sql9`COUNT(*)`;
|
|
2991
|
-
return {
|
|
2992
|
-
active: sql9`${conversationCount} FILTER (
|
|
2993
|
-
WHERE ${roots.executionStatus} NOT IN ('idle', 'failed')
|
|
2994
|
-
)::integer`,
|
|
2995
|
-
conversations: sql9`${conversationCount}::integer`,
|
|
2996
|
-
cachedInputTokens: sql9`SUM(${usageTokenValue(metrics, "cachedInputTokens")})::double precision`,
|
|
2997
|
-
costUsd: sql9`SUM(${costValue(metrics)})::double precision`,
|
|
2998
|
-
durationMs: sql9`COALESCE(SUM(${metrics.durationMs}), 0)::double precision`,
|
|
2999
|
-
failed: sql9`${conversationCount} FILTER (
|
|
3000
|
-
WHERE ${roots.executionStatus} = 'failed'
|
|
3001
|
-
)::integer`,
|
|
3002
|
-
inputTokens: sql9`SUM(${usageTokenValue(metrics, "inputTokens")})::double precision`,
|
|
3003
|
-
tokens: sql9`SUM(${tokenValue(metrics)})::double precision`
|
|
3004
|
-
};
|
|
3005
|
-
}
|
|
3006
|
-
function conversationRangeColumns() {
|
|
3007
|
-
return {
|
|
3008
|
-
firstSeenAt: sql9`MIN(${juniorConversations.createdAt})`.mapWith(
|
|
3009
|
-
juniorConversations.createdAt
|
|
3010
|
-
),
|
|
3011
|
-
lastSeenAt: sql9`MAX(${juniorConversations.lastActivityAt})`.mapWith(
|
|
3012
|
-
juniorConversations.lastActivityAt
|
|
3013
|
-
)
|
|
3014
|
-
};
|
|
3015
|
-
}
|
|
3016
|
-
function conversationActiveDaysColumn() {
|
|
3017
|
-
return sql9`COUNT(DISTINCT (${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC')::date)::integer`;
|
|
3018
|
-
}
|
|
3019
|
-
|
|
3020
|
-
// src/api/conversations/stats.query.ts
|
|
3021
3036
|
var WINDOW_DAYS = 90;
|
|
3022
3037
|
var treeConversation = alias3(juniorConversations, "stats_tree_conversation");
|
|
3023
3038
|
var treeAggregateColumns = conversationAggregateColumns({
|
|
@@ -3092,15 +3107,7 @@ function statsWindow(nowMs) {
|
|
|
3092
3107
|
return { end, start };
|
|
3093
3108
|
}
|
|
3094
3109
|
var HOUR_MS2 = 60 * 60 * 1e3;
|
|
3095
|
-
var WINDOW_HOURS =
|
|
3096
|
-
function startOfUtcHour(valueMs) {
|
|
3097
|
-
const date = new Date(valueMs);
|
|
3098
|
-
date.setUTCMinutes(0, 0, 0);
|
|
3099
|
-
return date;
|
|
3100
|
-
}
|
|
3101
|
-
function utcHourKey2(value) {
|
|
3102
|
-
return value.toISOString().slice(0, 13);
|
|
3103
|
-
}
|
|
3110
|
+
var WINDOW_HOURS = WINDOW_SEVEN_DAY_HOURS;
|
|
3104
3111
|
function metricPoint(date, row) {
|
|
3105
3112
|
return {
|
|
3106
3113
|
conversations: row?.conversations ?? 0,
|
|
@@ -3125,13 +3132,33 @@ function metricDays(rows, endMs) {
|
|
|
3125
3132
|
}
|
|
3126
3133
|
return days;
|
|
3127
3134
|
}
|
|
3135
|
+
function emptyMetricDay(date) {
|
|
3136
|
+
return { conversations: 0, date, durationMs: 0 };
|
|
3137
|
+
}
|
|
3138
|
+
function emptyGuardianDay(date) {
|
|
3139
|
+
return { allow: 0, ask: 0, date, deny: 0, requests: 0 };
|
|
3140
|
+
}
|
|
3141
|
+
function sumMetricHoursIntoSixHours(hours, endMs) {
|
|
3142
|
+
return sumUtcHoursIntoSixHours({
|
|
3143
|
+
empty: emptyMetricDay,
|
|
3144
|
+
hours,
|
|
3145
|
+
nowMs: endMs
|
|
3146
|
+
});
|
|
3147
|
+
}
|
|
3148
|
+
function sumGuardianHoursIntoSixHours(hours, endMs) {
|
|
3149
|
+
return sumUtcHoursIntoSixHours({
|
|
3150
|
+
empty: emptyGuardianDay,
|
|
3151
|
+
hours,
|
|
3152
|
+
nowMs: endMs
|
|
3153
|
+
});
|
|
3154
|
+
}
|
|
3128
3155
|
function metricHours(rows, endMs) {
|
|
3129
3156
|
const byHour = new Map(rows.map((row) => [row.date, row]));
|
|
3130
3157
|
const end = startOfUtcHour(endMs);
|
|
3131
3158
|
const start = new Date(end.getTime() - (WINDOW_HOURS - 1) * HOUR_MS2);
|
|
3132
3159
|
const hours = [];
|
|
3133
3160
|
for (const cursor = new Date(start); cursor.getTime() <= end.getTime(); cursor.setTime(cursor.getTime() + HOUR_MS2)) {
|
|
3134
|
-
const date =
|
|
3161
|
+
const date = utcHourKey(cursor);
|
|
3135
3162
|
hours.push(metricPoint(date, byHour.get(date)));
|
|
3136
3163
|
}
|
|
3137
3164
|
return hours;
|
|
@@ -3175,7 +3202,7 @@ function guardianStats(dayRows, hourRows, endMs) {
|
|
|
3175
3202
|
const hourStart = new Date(hourEnd.getTime() - (WINDOW_HOURS - 1) * HOUR_MS2);
|
|
3176
3203
|
const metricHours2 = [];
|
|
3177
3204
|
for (const cursor = new Date(hourStart); cursor.getTime() <= hourEnd.getTime(); cursor.setTime(cursor.getTime() + HOUR_MS2)) {
|
|
3178
|
-
const date =
|
|
3205
|
+
const date = utcHourKey(cursor);
|
|
3179
3206
|
metricHours2.push(guardianPoint(date, byHour.get(date)));
|
|
3180
3207
|
}
|
|
3181
3208
|
return {
|
|
@@ -3184,17 +3211,18 @@ function guardianStats(dayRows, hourRows, endMs) {
|
|
|
3184
3211
|
deny,
|
|
3185
3212
|
metricDays: metricDays2,
|
|
3186
3213
|
metricHours: metricHours2,
|
|
3214
|
+
metricSixHours: sumGuardianHoursIntoSixHours(metricHours2, endMs),
|
|
3187
3215
|
requests,
|
|
3188
3216
|
...costUsd !== void 0 ? { costUsd } : void 0
|
|
3189
3217
|
};
|
|
3190
3218
|
}
|
|
3191
3219
|
async function aggregateStats(db, start, end) {
|
|
3192
3220
|
const where = statsWhere(start, end);
|
|
3193
|
-
const activityDate =
|
|
3221
|
+
const activityDate = sql9`TO_CHAR(
|
|
3194
3222
|
${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC',
|
|
3195
3223
|
'YYYY-MM-DD'
|
|
3196
3224
|
)`;
|
|
3197
|
-
const activityHour =
|
|
3225
|
+
const activityHour = sql9`TO_CHAR(
|
|
3198
3226
|
${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC',
|
|
3199
3227
|
'YYYY-MM-DD"T"HH24'
|
|
3200
3228
|
)`;
|
|
@@ -3302,26 +3330,26 @@ async function aggregateStats(db, start, end) {
|
|
|
3302
3330
|
};
|
|
3303
3331
|
}
|
|
3304
3332
|
async function aggregateGuardianStats(db, start, end) {
|
|
3305
|
-
const day =
|
|
3333
|
+
const day = sql9`TO_CHAR(
|
|
3306
3334
|
${juniorConversationEvents.createdAt} AT TIME ZONE 'UTC',
|
|
3307
3335
|
'YYYY-MM-DD'
|
|
3308
3336
|
)`;
|
|
3309
|
-
const hour =
|
|
3337
|
+
const hour = sql9`TO_CHAR(
|
|
3310
3338
|
${juniorConversationEvents.createdAt} AT TIME ZONE 'UTC',
|
|
3311
3339
|
'YYYY-MM-DD"T"HH24'
|
|
3312
3340
|
)`;
|
|
3313
|
-
const decision =
|
|
3314
|
-
const cost2 =
|
|
3341
|
+
const decision = sql9`${juniorConversationEvents.payload}->>'decision'`;
|
|
3342
|
+
const cost2 = sql9`CASE
|
|
3315
3343
|
WHEN jsonb_typeof(${juniorConversationEvents.payload}->'costUsd') = 'number'
|
|
3316
3344
|
THEN (${juniorConversationEvents.payload}->>'costUsd')::double precision
|
|
3317
3345
|
ELSE NULL
|
|
3318
3346
|
END`;
|
|
3319
3347
|
const selectColumns = {
|
|
3320
|
-
allow:
|
|
3321
|
-
ask:
|
|
3322
|
-
costUsd:
|
|
3323
|
-
deny:
|
|
3324
|
-
requests:
|
|
3348
|
+
allow: sql9`COUNT(*) FILTER (WHERE ${decision} = 'allow')::integer`,
|
|
3349
|
+
ask: sql9`COUNT(*) FILTER (WHERE ${decision} = 'ask')::integer`,
|
|
3350
|
+
costUsd: sql9`SUM(${cost2})::double precision`,
|
|
3351
|
+
deny: sql9`COUNT(*) FILTER (WHERE ${decision} = 'deny')::integer`,
|
|
3352
|
+
requests: sql9`COUNT(*)::integer`
|
|
3325
3353
|
};
|
|
3326
3354
|
const where = and10(
|
|
3327
3355
|
eq10(juniorConversationEvents.type, "guardian_action_reviewed"),
|
|
@@ -3362,7 +3390,13 @@ async function readConversationStatsFromSql() {
|
|
|
3362
3390
|
generatedAt: new Date(nowMs).toISOString(),
|
|
3363
3391
|
guardian: guardianStats(guardian.dayRows, guardian.hourRows, nowMs),
|
|
3364
3392
|
metricDays: metricDays(metricRows, nowMs),
|
|
3365
|
-
|
|
3393
|
+
...(() => {
|
|
3394
|
+
const hours = metricHours(metricHourRows, nowMs);
|
|
3395
|
+
return {
|
|
3396
|
+
metricHours: hours,
|
|
3397
|
+
metricSixHours: sumMetricHoursIntoSixHours(hours, nowMs)
|
|
3398
|
+
};
|
|
3399
|
+
})(),
|
|
3366
3400
|
locations: statsItems(locations),
|
|
3367
3401
|
actors: statsItems(actors),
|
|
3368
3402
|
source: "conversation_index",
|
|
@@ -3596,7 +3630,7 @@ function createConversationRoutes(options) {
|
|
|
3596
3630
|
import { Hono as Hono2 } from "hono";
|
|
3597
3631
|
|
|
3598
3632
|
// src/api/code/overview.ts
|
|
3599
|
-
import { desc as
|
|
3633
|
+
import { desc as desc5, eq as eq11, gte as gte2, or as or5, sql as sql10 } from "drizzle-orm";
|
|
3600
3634
|
import { z as z5 } from "zod";
|
|
3601
3635
|
var DAY_MS2 = 24 * 60 * 60 * 1e3;
|
|
3602
3636
|
var WINDOW_DAYS2 = 30;
|
|
@@ -3651,7 +3685,7 @@ function mergeRate(merged, closed) {
|
|
|
3651
3685
|
return completed > 0 ? merged / completed : void 0;
|
|
3652
3686
|
}
|
|
3653
3687
|
function conversationTreeCostExpr() {
|
|
3654
|
-
return
|
|
3688
|
+
return sql10`
|
|
3655
3689
|
coalesce((
|
|
3656
3690
|
SELECT sum(
|
|
3657
3691
|
CASE
|
|
@@ -3680,7 +3714,7 @@ function conversationTreeCostExpr() {
|
|
|
3680
3714
|
`;
|
|
3681
3715
|
}
|
|
3682
3716
|
function ownedByUserSql(conversationIds, userId) {
|
|
3683
|
-
return
|
|
3717
|
+
return sql10`EXISTS (
|
|
3684
3718
|
SELECT 1
|
|
3685
3719
|
FROM unnest(${conversationIds}) AS linked(conversation_id)
|
|
3686
3720
|
INNER JOIN junior_conversations AS conversations
|
|
@@ -3692,7 +3726,7 @@ function ownedByUserSql(conversationIds, userId) {
|
|
|
3692
3726
|
}
|
|
3693
3727
|
function ownershipFilter(userId) {
|
|
3694
3728
|
if (!userId) return void 0;
|
|
3695
|
-
return ownedByUserSql(
|
|
3729
|
+
return ownedByUserSql(sql10`${juniorCodeChanges.conversationIds}`, userId);
|
|
3696
3730
|
}
|
|
3697
3731
|
async function readCodeWindows(args) {
|
|
3698
3732
|
const db = getDb();
|
|
@@ -3705,10 +3739,10 @@ async function readCodeWindows(args) {
|
|
|
3705
3739
|
const activityHourEnd = new Date(args.nowMs);
|
|
3706
3740
|
activityHourEnd.setUTCMinutes(0, 0, 0);
|
|
3707
3741
|
const activityHourStart = new Date(
|
|
3708
|
-
activityHourEnd.getTime() -
|
|
3742
|
+
activityHourEnd.getTime() - (7 * 24 - 1) * (DAY_MS2 / 24)
|
|
3709
3743
|
);
|
|
3710
3744
|
const [summaryResult, activityResult, activityHourResult] = await Promise.all([
|
|
3711
|
-
db.execute(
|
|
3745
|
+
db.execute(sql10`
|
|
3712
3746
|
WITH recent_changes AS (
|
|
3713
3747
|
SELECT
|
|
3714
3748
|
${changes.id},
|
|
@@ -3718,7 +3752,7 @@ async function readCodeWindows(args) {
|
|
|
3718
3752
|
${changes.state},
|
|
3719
3753
|
${changes.conversationIds} AS conversation_ids
|
|
3720
3754
|
FROM ${changes}
|
|
3721
|
-
${ownership ?
|
|
3755
|
+
${ownership ? sql10`WHERE ${ownership}` : sql10``}
|
|
3722
3756
|
), change_costs AS (
|
|
3723
3757
|
SELECT
|
|
3724
3758
|
recent_changes.id,
|
|
@@ -3767,7 +3801,7 @@ async function readCodeWindows(args) {
|
|
|
3767
3801
|
)::double precision AS "medianCostUsd"
|
|
3768
3802
|
FROM recent_changes
|
|
3769
3803
|
`),
|
|
3770
|
-
db.execute(
|
|
3804
|
+
db.execute(sql10`
|
|
3771
3805
|
WITH days AS (
|
|
3772
3806
|
SELECT generate_series(
|
|
3773
3807
|
date_trunc('day', ${activityStart}::timestamptz AT TIME ZONE 'UTC'),
|
|
@@ -3784,18 +3818,18 @@ async function readCodeWindows(args) {
|
|
|
3784
3818
|
SELECT ${changes.openedAt} AS event_at, 'created'::text AS kind
|
|
3785
3819
|
FROM ${changes}
|
|
3786
3820
|
WHERE ${changes.openedAt} >= ${activityStart}
|
|
3787
|
-
${ownership ?
|
|
3821
|
+
${ownership ? sql10`AND ${ownership}` : sql10``}
|
|
3788
3822
|
UNION ALL
|
|
3789
3823
|
SELECT ${changes.mergedAt} AS event_at, 'merged'::text AS kind
|
|
3790
3824
|
FROM ${changes}
|
|
3791
3825
|
WHERE ${changes.mergedAt} >= ${activityStart}
|
|
3792
|
-
${ownership ?
|
|
3826
|
+
${ownership ? sql10`AND ${ownership}` : sql10``}
|
|
3793
3827
|
UNION ALL
|
|
3794
3828
|
SELECT ${changes.closedAt} AS event_at, 'closed'::text AS kind
|
|
3795
3829
|
FROM ${changes}
|
|
3796
3830
|
WHERE ${changes.state} = 'closed'
|
|
3797
3831
|
AND ${changes.closedAt} >= ${activityStart}
|
|
3798
|
-
${ownership ?
|
|
3832
|
+
${ownership ? sql10`AND ${ownership}` : sql10``}
|
|
3799
3833
|
) AS events
|
|
3800
3834
|
GROUP BY date_trunc('day', event_at AT TIME ZONE 'UTC')
|
|
3801
3835
|
)
|
|
@@ -3808,7 +3842,7 @@ async function readCodeWindows(args) {
|
|
|
3808
3842
|
LEFT JOIN daily ON daily.day = days.day
|
|
3809
3843
|
ORDER BY days.day
|
|
3810
3844
|
`),
|
|
3811
|
-
db.execute(
|
|
3845
|
+
db.execute(sql10`
|
|
3812
3846
|
WITH hours AS (
|
|
3813
3847
|
SELECT generate_series(
|
|
3814
3848
|
date_trunc('hour', ${activityHourStart}::timestamptz AT TIME ZONE 'UTC'),
|
|
@@ -3825,18 +3859,18 @@ async function readCodeWindows(args) {
|
|
|
3825
3859
|
SELECT ${changes.openedAt} AS event_at, 'created'::text AS kind
|
|
3826
3860
|
FROM ${changes}
|
|
3827
3861
|
WHERE ${changes.openedAt} >= ${activityHourStart}
|
|
3828
|
-
${ownership ?
|
|
3862
|
+
${ownership ? sql10`AND ${ownership}` : sql10``}
|
|
3829
3863
|
UNION ALL
|
|
3830
3864
|
SELECT ${changes.mergedAt} AS event_at, 'merged'::text AS kind
|
|
3831
3865
|
FROM ${changes}
|
|
3832
3866
|
WHERE ${changes.mergedAt} >= ${activityHourStart}
|
|
3833
|
-
${ownership ?
|
|
3867
|
+
${ownership ? sql10`AND ${ownership}` : sql10``}
|
|
3834
3868
|
UNION ALL
|
|
3835
3869
|
SELECT ${changes.closedAt} AS event_at, 'closed'::text AS kind
|
|
3836
3870
|
FROM ${changes}
|
|
3837
3871
|
WHERE ${changes.state} = 'closed'
|
|
3838
3872
|
AND ${changes.closedAt} >= ${activityHourStart}
|
|
3839
|
-
${ownership ?
|
|
3873
|
+
${ownership ? sql10`AND ${ownership}` : sql10``}
|
|
3840
3874
|
) AS events
|
|
3841
3875
|
GROUP BY date_trunc('hour', event_at AT TIME ZONE 'UTC')
|
|
3842
3876
|
)
|
|
@@ -3861,9 +3895,15 @@ async function readCodeWindows(args) {
|
|
|
3861
3895
|
open: 0
|
|
3862
3896
|
}
|
|
3863
3897
|
);
|
|
3898
|
+
const activityHours3 = z5.array(activityDaySchema).parse(queryRows(activityHourResult));
|
|
3864
3899
|
return {
|
|
3865
3900
|
activityDays: z5.array(activityDaySchema).parse(queryRows(activityResult)),
|
|
3866
|
-
activityHours:
|
|
3901
|
+
activityHours: activityHours3,
|
|
3902
|
+
activitySixHours: sumUtcHoursIntoSixHours({
|
|
3903
|
+
empty: (date) => ({ closed: 0, created: 0, date, merged: 0 }),
|
|
3904
|
+
hours: activityHours3,
|
|
3905
|
+
nowMs: args.nowMs
|
|
3906
|
+
}),
|
|
3867
3907
|
summary: {
|
|
3868
3908
|
...summary,
|
|
3869
3909
|
mergeRate: mergeRate(summary.merged, summary.closed)
|
|
@@ -3879,7 +3919,7 @@ async function readCodeOverview(nowMs = Date.now()) {
|
|
|
3879
3919
|
const windows = await readCodeWindows({ nowMs });
|
|
3880
3920
|
const conversationTreeCost = conversationTreeCostExpr();
|
|
3881
3921
|
const [repositoryResult, recentChanges] = await Promise.all([
|
|
3882
|
-
db.execute(
|
|
3922
|
+
db.execute(sql10`
|
|
3883
3923
|
WITH recent_changes AS (
|
|
3884
3924
|
SELECT
|
|
3885
3925
|
${changes.id},
|
|
@@ -3956,11 +3996,12 @@ async function readCodeOverview(nowMs = Date.now()) {
|
|
|
3956
3996
|
gte2(changes.closedAt, windows.windowStart),
|
|
3957
3997
|
eq11(changes.state, "open")
|
|
3958
3998
|
)
|
|
3959
|
-
).orderBy(
|
|
3999
|
+
).orderBy(desc5(changes.updatedAt)).limit(25)
|
|
3960
4000
|
]);
|
|
3961
4001
|
return codeOverviewReportSchema.parse({
|
|
3962
4002
|
activityDays: windows.activityDays,
|
|
3963
4003
|
activityHours: windows.activityHours,
|
|
4004
|
+
activitySixHours: windows.activitySixHours,
|
|
3964
4005
|
changes: recentChanges.map((change) => ({
|
|
3965
4006
|
...change,
|
|
3966
4007
|
closedAt: change.closedAt?.toISOString(),
|
|
@@ -3989,6 +4030,7 @@ async function readPersonCodeOverview(args) {
|
|
|
3989
4030
|
return codePersonReportSchema.parse({
|
|
3990
4031
|
activityDays: windows.activityDays,
|
|
3991
4032
|
activityHours: windows.activityHours,
|
|
4033
|
+
activitySixHours: windows.activitySixHours,
|
|
3992
4034
|
generatedAt: windows.windowEnd.toISOString(),
|
|
3993
4035
|
summary: windows.summary,
|
|
3994
4036
|
windowEnd: windows.windowEnd.toISOString(),
|
|
@@ -4010,7 +4052,7 @@ function createCodeRoutes() {
|
|
|
4010
4052
|
import { Hono as Hono3 } from "hono";
|
|
4011
4053
|
|
|
4012
4054
|
// src/api/locations/query.ts
|
|
4013
|
-
import { and as and11, asc as asc3, desc as
|
|
4055
|
+
import { and as and11, asc as asc3, desc as desc6, eq as eq12, gte as gte3, isNull as isNull5, sql as sql11 } from "drizzle-orm";
|
|
4014
4056
|
import { alias as alias4 } from "drizzle-orm/pg-core";
|
|
4015
4057
|
|
|
4016
4058
|
// src/api/conversations/reporting.ts
|
|
@@ -4182,16 +4224,16 @@ async function directoryRows(db) {
|
|
|
4182
4224
|
).where(topLevelWhere()).groupBy(...locationGroupBy());
|
|
4183
4225
|
}
|
|
4184
4226
|
async function directoryActivityRows(db, start, hourStart) {
|
|
4185
|
-
const day =
|
|
4227
|
+
const day = sql11`TO_CHAR(
|
|
4186
4228
|
${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC',
|
|
4187
4229
|
'YYYY-MM-DD'
|
|
4188
4230
|
)`;
|
|
4189
|
-
const hour =
|
|
4231
|
+
const hour = sql11`TO_CHAR(
|
|
4190
4232
|
${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC',
|
|
4191
4233
|
'YYYY-MM-DD"T"HH24'
|
|
4192
4234
|
)`;
|
|
4193
4235
|
const select = {
|
|
4194
|
-
conversations:
|
|
4236
|
+
conversations: sql11`COUNT(*)::integer`,
|
|
4195
4237
|
visibility: juniorDestinations.visibility
|
|
4196
4238
|
};
|
|
4197
4239
|
const [dayRows, hourRows] = await Promise.all([
|
|
@@ -4243,15 +4285,29 @@ function directoryActivityDays(rows, nowMs) {
|
|
|
4243
4285
|
}
|
|
4244
4286
|
function directoryActivityHours(rows, nowMs) {
|
|
4245
4287
|
return fillUtcHours({
|
|
4288
|
+
count: WINDOW_SEVEN_DAY_HOURS,
|
|
4246
4289
|
empty: emptyLocationActivityDay,
|
|
4247
4290
|
nowMs,
|
|
4248
4291
|
rows: accumulateLocationActivity(rows)
|
|
4249
4292
|
});
|
|
4250
4293
|
}
|
|
4294
|
+
function directoryActivitySixHours(rows, nowMs) {
|
|
4295
|
+
const hours = fillUtcHours({
|
|
4296
|
+
count: WINDOW_SEVEN_DAY_HOURS,
|
|
4297
|
+
empty: emptyLocationActivityDay,
|
|
4298
|
+
nowMs,
|
|
4299
|
+
rows: accumulateLocationActivity(rows)
|
|
4300
|
+
});
|
|
4301
|
+
return sumUtcHoursIntoSixHours({
|
|
4302
|
+
empty: emptyLocationActivityDay,
|
|
4303
|
+
hours,
|
|
4304
|
+
nowMs
|
|
4305
|
+
});
|
|
4306
|
+
}
|
|
4251
4307
|
async function readLocationDirectoryFromSql() {
|
|
4252
4308
|
const nowMs = Date.now();
|
|
4253
4309
|
const { end, start } = trailingUtcDayWindow(nowMs, ACTIVITY_DAYS2);
|
|
4254
|
-
const hourWindow = trailingUtcHourWindow(nowMs);
|
|
4310
|
+
const hourWindow = trailingUtcHourWindow(nowMs, WINDOW_SEVEN_DAY_HOURS);
|
|
4255
4311
|
const [rows, activity] = await Promise.all([
|
|
4256
4312
|
directoryRows(getDb()),
|
|
4257
4313
|
directoryActivityRows(getDb(), start, hourWindow.start)
|
|
@@ -4269,6 +4325,7 @@ async function readLocationDirectoryFromSql() {
|
|
|
4269
4325
|
return {
|
|
4270
4326
|
activityDays: directoryActivityDays(activity.dayRows, nowMs),
|
|
4271
4327
|
activityHours: directoryActivityHours(activity.hourRows, nowMs),
|
|
4328
|
+
activitySixHours: directoryActivitySixHours(activity.hourRows, nowMs),
|
|
4272
4329
|
generatedAt: new Date(nowMs).toISOString(),
|
|
4273
4330
|
locations: locations.sort(
|
|
4274
4331
|
(left, right) => Date.parse(right.lastSeenAt) - Date.parse(left.lastSeenAt) || right.conversations - left.conversations || left.label.localeCompare(right.label)
|
|
@@ -4286,7 +4343,7 @@ async function recentLocationRows(db, locationId) {
|
|
|
4286
4343
|
createdAt: juniorConversations.createdAt,
|
|
4287
4344
|
destinationId: juniorDestinations.id,
|
|
4288
4345
|
durationMs: juniorConversations.durationMs,
|
|
4289
|
-
email:
|
|
4346
|
+
email: sql11`COALESCE(
|
|
4290
4347
|
${juniorUsers.primaryEmailNormalized},
|
|
4291
4348
|
${juniorIdentities.email}
|
|
4292
4349
|
)`,
|
|
@@ -4295,7 +4352,7 @@ async function recentLocationRows(db, locationId) {
|
|
|
4295
4352
|
fullName: juniorUsers.displayName,
|
|
4296
4353
|
handle: juniorIdentities.handle,
|
|
4297
4354
|
lastActivityAt: juniorConversations.lastActivityAt,
|
|
4298
|
-
providerSubjectId:
|
|
4355
|
+
providerSubjectId: sql11`CASE
|
|
4299
4356
|
WHEN ${juniorIdentities.provider} = 'slack'
|
|
4300
4357
|
THEN ${juniorIdentities.providerSubjectId}
|
|
4301
4358
|
ELSE NULL
|
|
@@ -4311,20 +4368,20 @@ async function recentLocationRows(db, locationId) {
|
|
|
4311
4368
|
juniorIdentities,
|
|
4312
4369
|
eq12(juniorIdentities.id, juniorConversations.actorIdentityId)
|
|
4313
4370
|
).leftJoin(juniorUsers, eq12(juniorUsers.id, juniorIdentities.userId)).where(publicLocationWhere(locationId)).orderBy(
|
|
4314
|
-
|
|
4371
|
+
desc6(juniorConversations.lastActivityAt),
|
|
4315
4372
|
asc3(juniorConversations.conversationId)
|
|
4316
4373
|
).limit(RECENT_LIMIT);
|
|
4317
4374
|
}
|
|
4318
4375
|
async function readLocationDetailFromSql(locationId, options = {}) {
|
|
4319
4376
|
const nowMs = Date.now();
|
|
4320
4377
|
const { end, start } = trailingUtcDayWindow(nowMs, ACTIVITY_DAYS2);
|
|
4321
|
-
const hourWindow = trailingUtcHourWindow(nowMs);
|
|
4378
|
+
const hourWindow = trailingUtcHourWindow(nowMs, WINDOW_SEVEN_DAY_HOURS);
|
|
4322
4379
|
const where = publicLocationWhere(locationId);
|
|
4323
|
-
const activityDate =
|
|
4380
|
+
const activityDate = sql11`TO_CHAR(
|
|
4324
4381
|
${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC',
|
|
4325
4382
|
'YYYY-MM-DD'
|
|
4326
4383
|
)`;
|
|
4327
|
-
const activityHour =
|
|
4384
|
+
const activityHour = sql11`TO_CHAR(
|
|
4328
4385
|
${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC',
|
|
4329
4386
|
'YYYY-MM-DD"T"HH24'
|
|
4330
4387
|
)`;
|
|
@@ -4457,6 +4514,7 @@ async function readLocationDetailFromSql(locationId, options = {}) {
|
|
|
4457
4514
|
...location,
|
|
4458
4515
|
activityDays: activity,
|
|
4459
4516
|
activityHours: hourlyActivity,
|
|
4517
|
+
activitySixHours: activitySixHours(hourlyActivity, nowMs),
|
|
4460
4518
|
actors: actors.sort(
|
|
4461
4519
|
(left, right) => right.conversations - left.conversations || left.label.localeCompare(right.label)
|
|
4462
4520
|
),
|
|
@@ -4539,10 +4597,10 @@ async function readPeopleCode(email) {
|
|
|
4539
4597
|
}
|
|
4540
4598
|
|
|
4541
4599
|
// src/api/people/list.query.ts
|
|
4542
|
-
import { and as and13, eq as eq14, gte as gte4, sql as
|
|
4600
|
+
import { and as and13, eq as eq14, gte as gte4, sql as sql13 } from "drizzle-orm";
|
|
4543
4601
|
|
|
4544
4602
|
// src/api/people/shared.ts
|
|
4545
|
-
import { and as and12, asc as asc4, desc as
|
|
4603
|
+
import { and as and12, asc as asc4, desc as desc7, eq as eq13, isNull as isNull6, notExists, or as or6, sql as sql12 } from "drizzle-orm";
|
|
4546
4604
|
import { alias as alias5 } from "drizzle-orm/pg-core";
|
|
4547
4605
|
var RECENT_LIMIT2 = 25;
|
|
4548
4606
|
var ACTIVITY_DAYS3 = 365;
|
|
@@ -4633,11 +4691,20 @@ function activityDays2(days, nowMs) {
|
|
|
4633
4691
|
}
|
|
4634
4692
|
function activityHours2(hours, nowMs) {
|
|
4635
4693
|
return fillUtcHours({
|
|
4694
|
+
count: WINDOW_SEVEN_DAY_HOURS,
|
|
4636
4695
|
empty: emptyActivityDay,
|
|
4637
4696
|
nowMs,
|
|
4638
4697
|
rows: hours
|
|
4639
4698
|
});
|
|
4640
4699
|
}
|
|
4700
|
+
function activitySixHours2(hours, nowMs) {
|
|
4701
|
+
const series = hours instanceof Map ? activityHours2(hours, nowMs) : [...hours];
|
|
4702
|
+
return sumUtcHoursIntoSixHours({
|
|
4703
|
+
empty: emptyActivityDay,
|
|
4704
|
+
hours: series,
|
|
4705
|
+
nowMs
|
|
4706
|
+
});
|
|
4707
|
+
}
|
|
4641
4708
|
function statsItems2(map) {
|
|
4642
4709
|
return [...map.values()].sort(
|
|
4643
4710
|
(left, right) => right.conversations - left.conversations || right.durationMs - left.durationMs || left.label.localeCompare(right.label)
|
|
@@ -4648,7 +4715,7 @@ function verifiedActorWhere(email) {
|
|
|
4648
4715
|
return and12(
|
|
4649
4716
|
eq13(juniorIdentities.provider, "slack"),
|
|
4650
4717
|
eq13(juniorIdentities.emailVerified, true),
|
|
4651
|
-
|
|
4718
|
+
sql12`${juniorUsers.primaryEmailNormalized} IS NOT NULL`,
|
|
4652
4719
|
normalizedEmail ? eq13(juniorUsers.primaryEmailNormalized, normalizedEmail) : void 0
|
|
4653
4720
|
);
|
|
4654
4721
|
}
|
|
@@ -4677,7 +4744,7 @@ async function recentActorRows(email) {
|
|
|
4677
4744
|
juniorDestinations,
|
|
4678
4745
|
eq13(juniorDestinations.id, juniorConversations.destinationId)
|
|
4679
4746
|
).where(verifiedActorWhere(email)).orderBy(
|
|
4680
|
-
|
|
4747
|
+
desc7(juniorConversations.lastActivityAt),
|
|
4681
4748
|
asc4(juniorConversations.conversationId)
|
|
4682
4749
|
).limit(RECENT_LIMIT2);
|
|
4683
4750
|
}
|
|
@@ -4705,6 +4772,14 @@ function directoryActivityDays2(rows, nowMs) {
|
|
|
4705
4772
|
}
|
|
4706
4773
|
function directoryActivityHours2(rows, nowMs) {
|
|
4707
4774
|
return fillUtcHours({
|
|
4775
|
+
count: WINDOW_SEVEN_DAY_HOURS,
|
|
4776
|
+
empty: emptyDirectoryDay,
|
|
4777
|
+
nowMs,
|
|
4778
|
+
rows: new Map(rows.map((row) => [row.date, row]))
|
|
4779
|
+
});
|
|
4780
|
+
}
|
|
4781
|
+
function directoryActivitySixHours2(rows, nowMs) {
|
|
4782
|
+
return fillUtcSixHours({
|
|
4708
4783
|
empty: emptyDirectoryDay,
|
|
4709
4784
|
nowMs,
|
|
4710
4785
|
rows: new Map(rows.map((row) => [row.date, row]))
|
|
@@ -4782,33 +4857,40 @@ function buildActorWindows(args) {
|
|
|
4782
4857
|
async function readPeopleListFromSql() {
|
|
4783
4858
|
const nowMs = Date.now();
|
|
4784
4859
|
const { end, start } = trailingUtcDayWindow(nowMs, DIRECTORY_ACTIVITY_DAYS);
|
|
4785
|
-
const activityDate =
|
|
4860
|
+
const activityDate = sql13`TO_CHAR(
|
|
4786
4861
|
${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC',
|
|
4787
4862
|
'YYYY-MM-DD'
|
|
4788
4863
|
)`;
|
|
4789
|
-
const activityHour =
|
|
4864
|
+
const activityHour = sql13`TO_CHAR(
|
|
4790
4865
|
${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC',
|
|
4791
4866
|
'YYYY-MM-DD"T"HH24'
|
|
4792
4867
|
)`;
|
|
4793
|
-
const hourWindow = trailingUtcHourWindow(nowMs);
|
|
4868
|
+
const hourWindow = trailingUtcHourWindow(nowMs, WINDOW_SEVEN_DAY_HOURS);
|
|
4869
|
+
const sixHourWindow = trailingUtcSixHourWindow(nowMs);
|
|
4794
4870
|
const dayMetricStart = trailingUtcDayWindow(nowMs, DAY_METRIC_LOOKBACK).start;
|
|
4795
4871
|
const hourMetricStart = trailingUtcHourWindow(
|
|
4796
4872
|
nowMs,
|
|
4797
4873
|
HOUR_METRIC_LOOKBACK
|
|
4798
4874
|
).start;
|
|
4799
4875
|
const metricsJoin = peopleTreeMetricsJoin();
|
|
4876
|
+
const activitySixHour = sql13`TO_CHAR(
|
|
4877
|
+
date_trunc('day', ${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC')
|
|
4878
|
+
+ (FLOOR(EXTRACT(HOUR FROM ${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC') / 6) * INTERVAL '6 hours'),
|
|
4879
|
+
'YYYY-MM-DD"T"HH24'
|
|
4880
|
+
)`;
|
|
4800
4881
|
const [
|
|
4801
4882
|
rows,
|
|
4802
4883
|
activityRows,
|
|
4803
4884
|
activityHourRows,
|
|
4885
|
+
activitySixHourRows,
|
|
4804
4886
|
dayMetricRows,
|
|
4805
4887
|
hourMetricRows
|
|
4806
4888
|
] = await Promise.all([
|
|
4807
4889
|
getDb().select({
|
|
4808
4890
|
email: juniorUsers.primaryEmailNormalized,
|
|
4809
4891
|
fullName: juniorUsers.displayName,
|
|
4810
|
-
slackUserId:
|
|
4811
|
-
slackUserName:
|
|
4892
|
+
slackUserId: sql13`MAX(${juniorIdentities.providerSubjectId})`,
|
|
4893
|
+
slackUserName: sql13`MAX(${juniorIdentities.handle})`,
|
|
4812
4894
|
activeDays: conversationActiveDaysColumn(),
|
|
4813
4895
|
...peopleTreeAggregateColumns,
|
|
4814
4896
|
...conversationRangeColumns()
|
|
@@ -4817,8 +4899,8 @@ async function readPeopleListFromSql() {
|
|
|
4817
4899
|
eq14(juniorIdentities.id, juniorConversations.actorIdentityId)
|
|
4818
4900
|
).innerJoin(juniorUsers, eq14(juniorUsers.id, juniorIdentities.userId)).leftJoin(peopleTreeConversation, metricsJoin).where(verifiedActorWhere()).groupBy(juniorUsers.primaryEmailNormalized, juniorUsers.displayName),
|
|
4819
4901
|
getDb().select({
|
|
4820
|
-
activePeople:
|
|
4821
|
-
conversations:
|
|
4902
|
+
activePeople: sql13`COUNT(DISTINCT ${juniorUsers.id})::int`,
|
|
4903
|
+
conversations: sql13`COUNT(*)::int`,
|
|
4822
4904
|
date: activityDate
|
|
4823
4905
|
}).from(juniorConversations).innerJoin(
|
|
4824
4906
|
juniorIdentities,
|
|
@@ -4830,8 +4912,8 @@ async function readPeopleListFromSql() {
|
|
|
4830
4912
|
)
|
|
4831
4913
|
).groupBy(activityDate),
|
|
4832
4914
|
getDb().select({
|
|
4833
|
-
activePeople:
|
|
4834
|
-
conversations:
|
|
4915
|
+
activePeople: sql13`COUNT(DISTINCT ${juniorUsers.id})::int`,
|
|
4916
|
+
conversations: sql13`COUNT(*)::int`,
|
|
4835
4917
|
date: activityHour
|
|
4836
4918
|
}).from(juniorConversations).innerJoin(
|
|
4837
4919
|
juniorIdentities,
|
|
@@ -4842,6 +4924,19 @@ async function readPeopleListFromSql() {
|
|
|
4842
4924
|
gte4(juniorConversations.lastActivityAt, hourWindow.start)
|
|
4843
4925
|
)
|
|
4844
4926
|
).groupBy(activityHour),
|
|
4927
|
+
getDb().select({
|
|
4928
|
+
activePeople: sql13`COUNT(DISTINCT ${juniorUsers.id})::int`,
|
|
4929
|
+
conversations: sql13`COUNT(*)::int`,
|
|
4930
|
+
date: activitySixHour
|
|
4931
|
+
}).from(juniorConversations).innerJoin(
|
|
4932
|
+
juniorIdentities,
|
|
4933
|
+
eq14(juniorIdentities.id, juniorConversations.actorIdentityId)
|
|
4934
|
+
).innerJoin(juniorUsers, eq14(juniorUsers.id, juniorIdentities.userId)).where(
|
|
4935
|
+
and13(
|
|
4936
|
+
verifiedActorWhere(),
|
|
4937
|
+
gte4(juniorConversations.lastActivityAt, sixHourWindow.start)
|
|
4938
|
+
)
|
|
4939
|
+
).groupBy(activitySixHour),
|
|
4845
4940
|
getDb().select({
|
|
4846
4941
|
email: juniorUsers.primaryEmailNormalized,
|
|
4847
4942
|
date: activityDate,
|
|
@@ -4926,6 +5021,7 @@ async function readPeopleListFromSql() {
|
|
|
4926
5021
|
return {
|
|
4927
5022
|
activityDays: directoryActivityDays2(activityRows, nowMs),
|
|
4928
5023
|
activityHours: directoryActivityHours2(activityHourRows, nowMs),
|
|
5024
|
+
activitySixHours: directoryActivitySixHours2(activitySixHourRows, nowMs),
|
|
4929
5025
|
generatedAt: new Date(nowMs).toISOString(),
|
|
4930
5026
|
people: people.sort(
|
|
4931
5027
|
(left, right) => Date.parse(right.lastSeenAt) - Date.parse(left.lastSeenAt) || right.conversations - left.conversations || left.actor.email.localeCompare(right.actor.email)
|
|
@@ -4952,7 +5048,7 @@ async function readPeoplePluginReports(args) {
|
|
|
4952
5048
|
source: "plugins"
|
|
4953
5049
|
});
|
|
4954
5050
|
}
|
|
4955
|
-
const { getPluginProfileReports } = await import("./agent-hooks-
|
|
5051
|
+
const { getPluginProfileReports } = await import("./agent-hooks-VIBTIP5F.js");
|
|
4956
5052
|
return pluginOperationalReportFeedSchema.parse({
|
|
4957
5053
|
generatedAt: new Date(nowMs).toISOString(),
|
|
4958
5054
|
reports: await getPluginProfileReports({
|
|
@@ -4965,7 +5061,7 @@ async function readPeoplePluginReports(args) {
|
|
|
4965
5061
|
}
|
|
4966
5062
|
|
|
4967
5063
|
// src/api/people/profile.query.ts
|
|
4968
|
-
import { and as and14, eq as eq15, gte as gte5, sql as
|
|
5064
|
+
import { and as and14, eq as eq15, gte as gte5, sql as sql14 } from "drizzle-orm";
|
|
4969
5065
|
function emptyProfile(email, nowMs) {
|
|
4970
5066
|
const end = new Date(nowMs);
|
|
4971
5067
|
end.setUTCHours(0, 0, 0, 0);
|
|
@@ -4974,6 +5070,7 @@ function emptyProfile(email, nowMs) {
|
|
|
4974
5070
|
return {
|
|
4975
5071
|
activityDays: activityDays2(/* @__PURE__ */ new Map(), nowMs),
|
|
4976
5072
|
activityHours: activityHours2(/* @__PURE__ */ new Map(), nowMs),
|
|
5073
|
+
activitySixHours: activitySixHours2(/* @__PURE__ */ new Map(), nowMs),
|
|
4977
5074
|
generatedAt: new Date(nowMs).toISOString(),
|
|
4978
5075
|
locations: [],
|
|
4979
5076
|
recentConversations: [],
|
|
@@ -5001,7 +5098,7 @@ function addAggregate2(map, label, row) {
|
|
|
5001
5098
|
map.set(label, item);
|
|
5002
5099
|
}
|
|
5003
5100
|
function surfaceExpression() {
|
|
5004
|
-
return
|
|
5101
|
+
return sql14`CASE
|
|
5005
5102
|
WHEN ${juniorConversations.source} IN ('api', 'scheduler', 'slack')
|
|
5006
5103
|
THEN ${juniorConversations.source}
|
|
5007
5104
|
WHEN ${juniorConversations.conversationId} LIKE 'slack:%' THEN 'slack'
|
|
@@ -5030,22 +5127,22 @@ async function readPeopleProfileFromSql(email, options = {}) {
|
|
|
5030
5127
|
const where = verifiedActorWhere(normalizedEmail);
|
|
5031
5128
|
const metricsJoin = peopleTreeMetricsJoin();
|
|
5032
5129
|
const surface = surfaceExpression();
|
|
5033
|
-
const activityDate =
|
|
5130
|
+
const activityDate = sql14`TO_CHAR(
|
|
5034
5131
|
${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC',
|
|
5035
5132
|
'YYYY-MM-DD'
|
|
5036
5133
|
)`;
|
|
5037
|
-
const activityHour =
|
|
5134
|
+
const activityHour = sql14`TO_CHAR(
|
|
5038
5135
|
${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC',
|
|
5039
5136
|
'YYYY-MM-DD"T"HH24'
|
|
5040
5137
|
)`;
|
|
5041
|
-
const channel =
|
|
5042
|
-
const hourWindow = trailingUtcHourWindow(nowMs);
|
|
5138
|
+
const channel = sql14`SPLIT_PART(${juniorConversations.conversationId}, ':', 2)`;
|
|
5139
|
+
const hourWindow = trailingUtcHourWindow(nowMs, 7 * 24);
|
|
5043
5140
|
const [totalsRows, dayRows, hourRows, locationRows, surfaceRows, recentRows] = await Promise.all([
|
|
5044
5141
|
getDb().select({
|
|
5045
5142
|
email: juniorUsers.primaryEmailNormalized,
|
|
5046
5143
|
fullName: juniorUsers.displayName,
|
|
5047
|
-
slackUserId:
|
|
5048
|
-
slackUserName:
|
|
5144
|
+
slackUserId: sql14`MAX(${juniorIdentities.providerSubjectId})`,
|
|
5145
|
+
slackUserName: sql14`MAX(${juniorIdentities.handle})`,
|
|
5049
5146
|
activeDays: conversationActiveDaysColumn(),
|
|
5050
5147
|
...peopleTreeAggregateColumns
|
|
5051
5148
|
}).from(juniorConversations).innerJoin(
|
|
@@ -5148,6 +5245,7 @@ async function readPeopleProfileFromSql(email, options = {}) {
|
|
|
5148
5245
|
return {
|
|
5149
5246
|
activityDays: activityDays2(days, nowMs),
|
|
5150
5247
|
activityHours: activityHours2(hours, nowMs),
|
|
5248
|
+
activitySixHours: activitySixHours2(hours, nowMs),
|
|
5151
5249
|
generatedAt: new Date(nowMs).toISOString(),
|
|
5152
5250
|
locations: statsItems2(locations),
|
|
5153
5251
|
recentConversations: recentRows.map(
|
|
@@ -5180,7 +5278,7 @@ async function readPeopleProfile(email, options = {}) {
|
|
|
5180
5278
|
}
|
|
5181
5279
|
|
|
5182
5280
|
// src/api/people/spend.query.ts
|
|
5183
|
-
import { and as and15, eq as eq16, gte as gte6, lte as lte2, sql as
|
|
5281
|
+
import { and as and15, eq as eq16, gte as gte6, lte as lte2, sql as sql15 } from "drizzle-orm";
|
|
5184
5282
|
var SEVEN_DAY_OFFSET = 6;
|
|
5185
5283
|
var THIRTY_DAY_OFFSET = 29;
|
|
5186
5284
|
function addUsd3(current, next) {
|
|
@@ -5199,7 +5297,7 @@ function spendWindow(nowMs) {
|
|
|
5199
5297
|
async function readPersonalSpendFromSql(email, nowMs = Date.now()) {
|
|
5200
5298
|
const normalizedEmail = normalizeEmail(email);
|
|
5201
5299
|
const { end, sevenDayStart, thirtyDayStart } = spendWindow(nowMs);
|
|
5202
|
-
const activityDate =
|
|
5300
|
+
const activityDate = sql15`TO_CHAR(
|
|
5203
5301
|
${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC',
|
|
5204
5302
|
'YYYY-MM-DD'
|
|
5205
5303
|
)`;
|
|
@@ -5320,7 +5418,7 @@ import { Hono as Hono5 } from "hono";
|
|
|
5320
5418
|
|
|
5321
5419
|
// src/personal-tokens/store.ts
|
|
5322
5420
|
import { createHash, randomBytes, randomUUID } from "crypto";
|
|
5323
|
-
import { and as and16, desc as
|
|
5421
|
+
import { and as and16, desc as desc8, eq as eq17, gt, isNull as isNull7 } from "drizzle-orm";
|
|
5324
5422
|
var TOKEN_PREFIX = "jr_pat_";
|
|
5325
5423
|
var TOKEN_SUFFIX_LENGTH = 8;
|
|
5326
5424
|
var DEFAULT_TOKEN_LIFETIME_MS = 90 * 24 * 60 * 60 * 1e3;
|
|
@@ -5362,7 +5460,7 @@ async function listPersonalTokens(email, now = /* @__PURE__ */ new Date()) {
|
|
|
5362
5460
|
isNull7(juniorApiTokens.revokedAt),
|
|
5363
5461
|
gt(juniorApiTokens.expiresAt, now)
|
|
5364
5462
|
)
|
|
5365
|
-
).orderBy(
|
|
5463
|
+
).orderBy(desc8(juniorApiTokens.createdAt));
|
|
5366
5464
|
return rows.map(metadata);
|
|
5367
5465
|
}
|
|
5368
5466
|
async function revokePersonalToken(args) {
|
|
@@ -5784,7 +5882,7 @@ function readDescriptionText(home) {
|
|
|
5784
5882
|
}
|
|
5785
5883
|
}
|
|
5786
5884
|
async function readSkillReports() {
|
|
5787
|
-
const { discoverSkills } = await import("./skills-
|
|
5885
|
+
const { discoverSkills } = await import("./skills-QTN73DN5.js");
|
|
5788
5886
|
const skills = await discoverSkills();
|
|
5789
5887
|
return skillReportsSchema.parse(
|
|
5790
5888
|
skills.map((skill) => ({
|
|
@@ -5794,7 +5892,7 @@ async function readSkillReports() {
|
|
|
5794
5892
|
);
|
|
5795
5893
|
}
|
|
5796
5894
|
async function readPlugins() {
|
|
5797
|
-
const { pluginCatalogRuntime } = await import("./catalog-runtime-
|
|
5895
|
+
const { pluginCatalogRuntime } = await import("./catalog-runtime-6E6SGRZK.js");
|
|
5798
5896
|
return pluginsSchema.parse(
|
|
5799
5897
|
pluginCatalogRuntime.getProviders().map((plugin) => ({
|
|
5800
5898
|
configKeys: plugin.manifest.configKeys ?? [],
|
|
@@ -5807,7 +5905,7 @@ async function readPlugins() {
|
|
|
5807
5905
|
async function readRuntimeInfoReport() {
|
|
5808
5906
|
const [{ homeDir }, { pluginCatalogRuntime }, plugins, skills] = await Promise.all([
|
|
5809
5907
|
import("./discovery-DWVDM7UK.js"),
|
|
5810
|
-
import("./catalog-runtime-
|
|
5908
|
+
import("./catalog-runtime-6E6SGRZK.js"),
|
|
5811
5909
|
readPlugins(),
|
|
5812
5910
|
readSkillReports()
|
|
5813
5911
|
]);
|
|
@@ -5823,7 +5921,7 @@ async function readRuntimeInfoReport() {
|
|
|
5823
5921
|
}
|
|
5824
5922
|
async function readPluginOperationalReportFeed() {
|
|
5825
5923
|
const nowMs = Date.now();
|
|
5826
|
-
const { getPluginOperationalReports } = await import("./agent-hooks-
|
|
5924
|
+
const { getPluginOperationalReports } = await import("./agent-hooks-VIBTIP5F.js");
|
|
5827
5925
|
return pluginOperationalReportFeedSchema.parse({
|
|
5828
5926
|
source: "plugins",
|
|
5829
5927
|
generatedAt: new Date(nowMs).toISOString(),
|