@sentry/junior 0.202.0 → 0.204.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.
Files changed (174) hide show
  1. package/dist/agent-CMyTD4DD.js +17509 -0
  2. package/dist/agent-hooks-Bbcp9e33.js +4040 -0
  3. package/dist/agent-runner-DNb1A49M.js +678 -0
  4. package/dist/api/schema.d.ts +2728 -2639
  5. package/dist/api/schema.js +4 -169
  6. package/dist/api.d.ts +23 -17
  7. package/dist/api.js +3881 -5326
  8. package/dist/app-B1TOqBI8.d.ts +246 -0
  9. package/dist/app.d.ts +4 -520
  10. package/dist/app.js +9522 -11875
  11. package/dist/auth-pause-state-DosEalIG.js +168 -0
  12. package/dist/catalog-runtime-BReos-D4.js +7 -0
  13. package/dist/checkpoint-CNrPyRJN.js +2450 -0
  14. package/dist/cli/chat.d.ts +20 -0
  15. package/dist/cli/chat.js +229 -336
  16. package/dist/cli/check.d.ts +8 -0
  17. package/dist/cli/check.js +513 -806
  18. package/dist/cli/env.d.ts +13 -0
  19. package/dist/cli/env.js +63 -12
  20. package/dist/cli/init.d.ts +3 -0
  21. package/dist/cli/init.js +90 -159
  22. package/dist/cli/main.d.ts +6 -0
  23. package/dist/cli/main.js +43 -64
  24. package/dist/cli/plugins.d.ts +13 -0
  25. package/dist/cli/plugins.js +148 -227
  26. package/dist/cli/run.d.ts +16 -0
  27. package/dist/cli/run.js +52 -8
  28. package/dist/cli/snapshot-create.d.ts +4 -0
  29. package/dist/cli/snapshot-create.js +71 -125
  30. package/dist/cli/upgrade.d.ts +15 -0
  31. package/dist/cli/upgrade.js +232 -335
  32. package/dist/config-nGCW1OTG.js +941 -0
  33. package/dist/context-B45_WqVX.js +298 -0
  34. package/dist/conversation-privacy-B4voFRSm.js +182 -0
  35. package/dist/conversation-work-C6y3T5Hx.js +51 -0
  36. package/dist/credential-sync-kXr1hvO1.js +2660 -0
  37. package/dist/db-BeyXKJOI.d.ts +5 -0
  38. package/dist/destinations-BeBiJeEM.js +29 -0
  39. package/dist/execution-stats-DWfSihcH.js +373 -0
  40. package/dist/executor-DcMSlI5c.js +721 -0
  41. package/dist/experimental-CIXf7Uye.js +46 -0
  42. package/dist/history-ClE4toxe.d.ts +32 -0
  43. package/dist/history-CqTuSAdI.js +441 -0
  44. package/dist/instrumentation.d.ts +3 -3
  45. package/dist/instrumentation.js +130 -176
  46. package/dist/job-queue-Drn_LXlM.js +63 -0
  47. package/dist/logging-BzAk1S_s.js +1210 -0
  48. package/dist/model-profile-CZmVoGdX.js +49 -0
  49. package/dist/nitro.d.ts +31 -36
  50. package/dist/nitro.js +275 -456
  51. package/dist/oauth-callback-server-JiftokvA.js +130 -0
  52. package/dist/oauth-relay-CdCnu80W.js +62 -0
  53. package/dist/package-discovery-7a9YqLhE.js +455 -0
  54. package/dist/pending-auth-CWmSdZVg.js +185 -0
  55. package/dist/plugin-module-BKGOXca2.js +81 -0
  56. package/dist/plugins-BI9A1vKA.d.ts +95 -0
  57. package/dist/plugins-egKWjgue.js +99 -0
  58. package/dist/private-trace-result-BLvBjy_e.js +16 -0
  59. package/dist/profile-CrT5nXbw.js +861 -0
  60. package/dist/registry-DH1xUo2N.js +1419 -0
  61. package/dist/reporting-schema-DosTN__Q.js +105 -0
  62. package/dist/resolve-CZHnfxaS.js +546 -0
  63. package/dist/rolldown-runtime-B4FMCO8f.js +28 -0
  64. package/dist/runner-CZV2sC46.js +392 -0
  65. package/dist/sandbox-egress-signals-bHZfmhbd.js +46 -0
  66. package/dist/schema-Rn8-XEaN.js +1140 -0
  67. package/dist/sentry-CD3SdJl-.js +26 -0
  68. package/dist/skills-CIcDQSgM.js +316 -0
  69. package/dist/spawn-DdkUFRmq.js +29 -0
  70. package/dist/stats-DTUbAb88.js +2634 -0
  71. package/dist/store-C5qxF2ac.d.ts +208 -0
  72. package/dist/task-queue-CJIR4RF7.js +136 -0
  73. package/dist/task-runner-D-O3A-Cp.js +639 -0
  74. package/dist/thread-state-CRc9jTJS.js +431 -0
  75. package/dist/turn-execution-BkinIdJF.js +47 -0
  76. package/dist/turn-lifecycle-DQV19VTW.js +54 -0
  77. package/dist/usage-D3EbSO7w.js +296 -0
  78. package/dist/usage-schema-CKaDkH_j.js +20 -0
  79. package/dist/validation-C2CR-OX3.js +40 -0
  80. package/dist/vercel-queue-DIkVcfK4.js +167 -0
  81. package/dist/vercel.d.ts +6 -6
  82. package/dist/vercel.js +14 -6
  83. package/dist/version-CnXZ614E.d.ts +5 -0
  84. package/dist/version-DxcWdoKa.js +8 -0
  85. package/dist/version.d.ts +2 -4
  86. package/dist/version.js +2 -6
  87. package/dist/web-authorization-RMBxAR_t.js +76 -0
  88. package/dist/web-input-3EPfpf55.js +494 -0
  89. package/dist/work-fGofI7Op.js +509 -0
  90. package/dist/worker-CsOLq-mR.js +625 -0
  91. package/package.json +9 -9
  92. package/dist/agent-hooks-UXITLYOK.js +0 -51
  93. package/dist/catalog-runtime-BG3JLLK2.js +0 -14
  94. package/dist/chunk-2LYHWMR4.js +0 -46
  95. package/dist/chunk-2MK3QBGA.js +0 -321
  96. package/dist/chunk-3PGQSKJV.js +0 -692
  97. package/dist/chunk-3UI3WFTX.js +0 -519
  98. package/dist/chunk-3Y47VMHV.js +0 -6
  99. package/dist/chunk-4UO6FK4G.js +0 -64
  100. package/dist/chunk-5NOPO64K.js +0 -198
  101. package/dist/chunk-5PKWYPFT.js +0 -2943
  102. package/dist/chunk-63NKKFJL.js +0 -1228
  103. package/dist/chunk-6AYH6252.js +0 -787
  104. package/dist/chunk-6Y5B5PEX.js +0 -80
  105. package/dist/chunk-7DHZP5KJ.js +0 -333
  106. package/dist/chunk-7H2VZTWN.js +0 -103
  107. package/dist/chunk-7NL7T6VU.js +0 -406
  108. package/dist/chunk-A76OIMYN.js +0 -102
  109. package/dist/chunk-AWMS3SPP.js +0 -58
  110. package/dist/chunk-B3LY5RCL.js +0 -229
  111. package/dist/chunk-BD2KT3OB.js +0 -36
  112. package/dist/chunk-BXCX5QKA.js +0 -2086
  113. package/dist/chunk-C6VVF43U.js +0 -81
  114. package/dist/chunk-CEMMLV5L.js +0 -98
  115. package/dist/chunk-CM5HNV2W.js +0 -131
  116. package/dist/chunk-DA2KGZZI.js +0 -13
  117. package/dist/chunk-DBVY6HLX.js +0 -64
  118. package/dist/chunk-DIB4GX3G.js +0 -8
  119. package/dist/chunk-DKIJ2RP5.js +0 -68
  120. package/dist/chunk-DL2KLKVH.js +0 -931
  121. package/dist/chunk-DWPN6SCH.js +0 -172
  122. package/dist/chunk-ELWOYVOY.js +0 -206
  123. package/dist/chunk-EWT7H65X.js +0 -506
  124. package/dist/chunk-FA6POGLH.js +0 -70
  125. package/dist/chunk-HMREVIO2.js +0 -135
  126. package/dist/chunk-IIWUT4FO.js +0 -820
  127. package/dist/chunk-JAL3CH4G.js +0 -27
  128. package/dist/chunk-JSJQEWBJ.js +0 -3295
  129. package/dist/chunk-KHKKHDLD.js +0 -387
  130. package/dist/chunk-LA6R4A7Q.js +0 -706
  131. package/dist/chunk-LOOU2DUR.js +0 -20428
  132. package/dist/chunk-M6FHWXE3.js +0 -700
  133. package/dist/chunk-M76HMB7M.js +0 -1856
  134. package/dist/chunk-MAGNK5J4.js +0 -1520
  135. package/dist/chunk-MTM5IFCY.js +0 -1190
  136. package/dist/chunk-N7TMSOZH.js +0 -235
  137. package/dist/chunk-NHJU2ZAL.js +0 -56
  138. package/dist/chunk-NSXKRGRT.js +0 -717
  139. package/dist/chunk-OWMPFXJA.js +0 -1764
  140. package/dist/chunk-PDO5BLNM.js +0 -22
  141. package/dist/chunk-PEQXYSSE.js +0 -45
  142. package/dist/chunk-PW4P4JYF.js +0 -1135
  143. package/dist/chunk-QB54UQUS.js +0 -320
  144. package/dist/chunk-QP3OGJXF.js +0 -105
  145. package/dist/chunk-RC745GGZ.js +0 -122
  146. package/dist/chunk-REOIRYPR.js +0 -37
  147. package/dist/chunk-SCOZRLZ4.js +0 -164
  148. package/dist/chunk-TXJSXBV5.js +0 -1433
  149. package/dist/chunk-TXKUKMVO.js +0 -417
  150. package/dist/chunk-U2GPUYAL.js +0 -3656
  151. package/dist/chunk-UIE3R5XU.js +0 -17
  152. package/dist/chunk-UXPG6ZIN.js +0 -84
  153. package/dist/chunk-VFUK3X5B.js +0 -50
  154. package/dist/chunk-WQSHDTTI.js +0 -1163
  155. package/dist/chunk-X6GDDWQH.js +0 -60
  156. package/dist/chunk-Y2CM7HXH.js +0 -111
  157. package/dist/chunk-Y7X25LFY.js +0 -15
  158. package/dist/chunk-YDUR3ZYW.js +0 -10
  159. package/dist/conversation-work-VIOQ5ZF3.js +0 -54
  160. package/dist/db-3L2MCVRI.js +0 -26
  161. package/dist/discovery-DWVDM7UK.js +0 -44
  162. package/dist/experimental-P5FZM4CU.js +0 -12
  163. package/dist/oauth-callback-server-YVV6C6T2.js +0 -243
  164. package/dist/oauth-relay-5XPVRPYB.js +0 -8
  165. package/dist/plugins-YTYJMMJF.js +0 -14
  166. package/dist/runner-LQ7RETDP.js +0 -522
  167. package/dist/sandbox-egress-signals-FIL7EGPR.js +0 -73
  168. package/dist/sentry-MB3NL3IR.js +0 -42
  169. package/dist/skills-XRWYEDCD.js +0 -27
  170. package/dist/spawn-RC6SJUAI.js +0 -42
  171. package/dist/task-runner-7DY7ARYH.js +0 -36
  172. package/dist/validation-7MNQGCJA.js +0 -17
  173. package/dist/work-COALHUCG.js +0 -51
  174. package/dist/worker-6MURZIPD.js +0 -24
@@ -1,506 +0,0 @@
1
- import {
2
- agentTurnCostUsd,
3
- agentTurnTotalTokens
4
- } from "./chunk-7DHZP5KJ.js";
5
- import {
6
- getDb
7
- } from "./chunk-M76HMB7M.js";
8
- import {
9
- juniorConversations,
10
- juniorTaskExecutions
11
- } from "./chunk-PW4P4JYF.js";
12
- import {
13
- logWarn
14
- } from "./chunk-MAGNK5J4.js";
15
-
16
- // src/chat/tasks/execution-stats.ts
17
- import {
18
- and,
19
- asc,
20
- count,
21
- desc,
22
- eq,
23
- gte,
24
- inArray,
25
- lte,
26
- max,
27
- or,
28
- sql as sql2
29
- } from "drizzle-orm";
30
-
31
- // src/api/conversations/aggregate.ts
32
- import { sql } from "drizzle-orm";
33
- function usageTokenValue(source, field) {
34
- return sql`CASE
35
- WHEN ${source.usage}->>${field} IS NOT NULL
36
- THEN (${source.usage}->>${field})::double precision
37
- ELSE NULL
38
- END`;
39
- }
40
- function tokenValue(source) {
41
- return sql`
42
- CASE
43
- WHEN COALESCE(
44
- ${source.usage}->>'inputTokens',
45
- ${source.usage}->>'outputTokens',
46
- ${source.usage}->>'cachedInputTokens',
47
- ${source.usage}->>'cacheCreationTokens'
48
- ) IS NOT NULL
49
- THEN COALESCE((${source.usage}->>'inputTokens')::double precision, 0)
50
- + COALESCE((${source.usage}->>'outputTokens')::double precision, 0)
51
- + COALESCE((${source.usage}->>'cachedInputTokens')::double precision, 0)
52
- + COALESCE((${source.usage}->>'cacheCreationTokens')::double precision, 0)
53
- WHEN ${source.usage}->>'totalTokens' IS NOT NULL
54
- THEN (${source.usage}->>'totalTokens')::double precision
55
- ELSE NULL
56
- END
57
- `;
58
- }
59
- function costValue(source) {
60
- return conversationUsageCostExpr(source.usage);
61
- }
62
- function conversationUsageCostExpr(usage) {
63
- return sql`
64
- CASE
65
- WHEN ${usage}->'cost'->>'total' IS NOT NULL
66
- THEN (${usage}->'cost'->>'total')::double precision
67
- WHEN COALESCE(
68
- ${usage}->'cost'->>'input',
69
- ${usage}->'cost'->>'output',
70
- ${usage}->'cost'->>'cacheRead',
71
- ${usage}->'cost'->>'cacheWrite'
72
- ) IS NOT NULL
73
- THEN COALESCE((${usage}->'cost'->>'input')::double precision, 0)
74
- + COALESCE((${usage}->'cost'->>'output')::double precision, 0)
75
- + COALESCE((${usage}->'cost'->>'cacheRead')::double precision, 0)
76
- + COALESCE((${usage}->'cost'->>'cacheWrite')::double precision, 0)
77
- ELSE NULL
78
- END
79
- `;
80
- }
81
- function conversationAggregateColumns(sources) {
82
- const metrics = sources?.metrics ?? juniorConversations;
83
- const roots = sources?.roots ?? juniorConversations;
84
- const conversationCount = sources ? sql`COUNT(DISTINCT ${roots.conversationId})` : sql`COUNT(*)`;
85
- return {
86
- active: sql`${conversationCount} FILTER (
87
- WHERE ${roots.executionStatus} NOT IN ('idle', 'failed')
88
- )::integer`,
89
- conversations: sql`${conversationCount}::integer`,
90
- cachedInputTokens: sql`SUM(${usageTokenValue(metrics, "cachedInputTokens")})::double precision`,
91
- costUsd: sql`SUM(${costValue(metrics)})::double precision`,
92
- durationMs: sql`COALESCE(SUM(${metrics.durationMs}), 0)::double precision`,
93
- failed: sql`${conversationCount} FILTER (
94
- WHERE ${roots.executionStatus} = 'failed'
95
- )::integer`,
96
- inputTokens: sql`SUM(${usageTokenValue(metrics, "inputTokens")})::double precision`,
97
- tokens: sql`SUM(${tokenValue(metrics)})::double precision`
98
- };
99
- }
100
- function conversationRangeColumns() {
101
- return {
102
- firstSeenAt: sql`MIN(${juniorConversations.createdAt})`.mapWith(
103
- juniorConversations.createdAt
104
- ),
105
- lastSeenAt: sql`MAX(${juniorConversations.lastActivityAt})`.mapWith(
106
- juniorConversations.lastActivityAt
107
- )
108
- };
109
- }
110
- function conversationActiveDaysColumn() {
111
- return sql`COUNT(DISTINCT (${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC')::date)::integer`;
112
- }
113
-
114
- // src/chat/tasks/execution-stats.ts
115
- var TASK_EXECUTION_TYPES = ["scheduled", "event"];
116
- var TASK_EXECUTION_STATUSES = [
117
- "blocked",
118
- "completed",
119
- "failed"
120
- ];
121
- function addUsd(current, next) {
122
- return Math.round((current + next) * 1e12) / 1e12;
123
- }
124
- var EMPTY_RUN_WINDOWS = { 1: 0, 7: 0, 30: 0, 90: 0 };
125
- function emptyTaskRunWindows() {
126
- return { ...EMPTY_RUN_WINDOWS };
127
- }
128
- function utcDate(nowMs) {
129
- return new Date(nowMs).toISOString().slice(0, 10);
130
- }
131
- function emptyDay(date) {
132
- return { costUsd: 0, date, event: 0, scheduled: 0 };
133
- }
134
- function emptyStatusDay(date) {
135
- return { blocked: 0, completed: 0, date, failed: 0 };
136
- }
137
- async function recordTaskExecution(type, taskId, options) {
138
- const namespace = options.namespace ?? "junior";
139
- const nowMs = options.nowMs ?? Date.now();
140
- const status = options.status ?? "completed";
141
- try {
142
- await getDb().insert(juniorTaskExecutions).values({
143
- ...options.conversationId ? { conversationId: options.conversationId } : void 0,
144
- executedAtMs: nowMs,
145
- executionId: options.executionId,
146
- kind: type,
147
- namespace,
148
- status,
149
- taskId
150
- }).onConflictDoNothing({
151
- target: [
152
- juniorTaskExecutions.kind,
153
- juniorTaskExecutions.namespace,
154
- juniorTaskExecutions.executionId
155
- ]
156
- });
157
- } catch (error) {
158
- logWarn("task.execution.stat_failed", {
159
- error,
160
- "app.task.execution.id": options.executionId,
161
- "app.task.execution.namespace": namespace,
162
- "app.task.execution.status": status,
163
- "app.task.execution.task_id": taskId,
164
- "app.task.execution.type": type
165
- });
166
- }
167
- }
168
- async function readTaskExecutionSummaries(type, namespace, options = {}) {
169
- const nowMs = options.nowMs ?? Date.now();
170
- const oneDayAgoMs = nowMs - 1 * 24 * 60 * 60 * 1e3;
171
- const sevenDaysAgoMs = nowMs - 7 * 24 * 60 * 60 * 1e3;
172
- const thirtyDaysAgoMs = nowMs - 30 * 24 * 60 * 60 * 1e3;
173
- const ninetyDaysAgoMs = nowMs - 90 * 24 * 60 * 60 * 1e3;
174
- const db = getDb();
175
- const latest = db.selectDistinctOn([juniorTaskExecutions.taskId], {
176
- conversationId: juniorTaskExecutions.conversationId,
177
- taskId: juniorTaskExecutions.taskId
178
- }).from(juniorTaskExecutions).where(
179
- and(
180
- eq(juniorTaskExecutions.kind, type),
181
- eq(juniorTaskExecutions.namespace, namespace)
182
- )
183
- ).orderBy(
184
- juniorTaskExecutions.taskId,
185
- desc(juniorTaskExecutions.executedAtMs),
186
- desc(juniorTaskExecutions.executionId)
187
- ).as("latest_task_execution");
188
- const rows = await db.select({
189
- lastConversationId: latest.conversationId,
190
- lastExecutedAtMs: max(juniorTaskExecutions.executedAtMs),
191
- runsLast1Day: sql2`count(*) filter (where ${juniorTaskExecutions.executedAtMs} >= ${oneDayAgoMs})::int`,
192
- runsLast7Days: sql2`count(*) filter (where ${juniorTaskExecutions.executedAtMs} >= ${sevenDaysAgoMs})::int`,
193
- runsLast30Days: sql2`count(*) filter (where ${juniorTaskExecutions.executedAtMs} >= ${thirtyDaysAgoMs})::int`,
194
- runsLast90Days: sql2`count(*) filter (where ${juniorTaskExecutions.executedAtMs} >= ${ninetyDaysAgoMs})::int`,
195
- taskId: juniorTaskExecutions.taskId,
196
- totalRuns: sql2`count(*)::int`
197
- }).from(juniorTaskExecutions).innerJoin(latest, eq(latest.taskId, juniorTaskExecutions.taskId)).where(
198
- and(
199
- eq(juniorTaskExecutions.kind, type),
200
- eq(juniorTaskExecutions.namespace, namespace)
201
- )
202
- ).groupBy(juniorTaskExecutions.taskId, latest.conversationId);
203
- return new Map(
204
- rows.map((row) => [
205
- row.taskId,
206
- {
207
- ...row.lastConversationId ? { lastConversationId: row.lastConversationId } : void 0,
208
- ...row.lastExecutedAtMs !== null ? { lastExecutedAtMs: row.lastExecutedAtMs } : void 0,
209
- runs: {
210
- 1: row.runsLast1Day,
211
- 7: row.runsLast7Days,
212
- 30: row.runsLast30Days,
213
- 90: row.runsLast90Days
214
- },
215
- totalRuns: row.totalRuns
216
- }
217
- ])
218
- );
219
- }
220
- async function readTaskExecutionDays(dayCount = 90, options = {}) {
221
- const nowMs = options.nowMs ?? Date.now();
222
- const end = utcDate(nowMs);
223
- const endMs = Date.parse(`${end}T23:59:59.999Z`);
224
- const startMs = Date.parse(`${end}T00:00:00.000Z`) - (dayCount - 1) * 864e5;
225
- const executionDate = sql2`to_char(to_timestamp(${juniorTaskExecutions.executedAtMs} / 1000.0) at time zone 'UTC', 'YYYY-MM-DD')`;
226
- const conversationCost = conversationUsageCostExpr(juniorConversations.usage);
227
- const rows = await getDb().select({
228
- count: count(),
229
- costUsd: sql2`SUM(${conversationCost})::double precision`,
230
- date: executionDate,
231
- kind: juniorTaskExecutions.kind
232
- }).from(juniorTaskExecutions).leftJoin(
233
- juniorConversations,
234
- eq(
235
- juniorConversations.conversationId,
236
- juniorTaskExecutions.conversationId
237
- )
238
- ).where(
239
- and(
240
- gte(juniorTaskExecutions.executedAtMs, startMs),
241
- lte(juniorTaskExecutions.executedAtMs, endMs),
242
- eq(juniorTaskExecutions.status, "completed")
243
- )
244
- ).groupBy(executionDate, juniorTaskExecutions.kind).orderBy(asc(executionDate), asc(juniorTaskExecutions.kind));
245
- const byDate = /* @__PURE__ */ new Map();
246
- for (let offset = 0; offset < dayCount; offset += 1) {
247
- const date = utcDate(startMs + offset * 864e5);
248
- byDate.set(date, emptyDay(date));
249
- }
250
- for (const row of rows) {
251
- const day = byDate.get(row.date);
252
- if (!day) continue;
253
- if (row.kind === "scheduled") day.scheduled = row.count;
254
- else if (row.kind === "event") day.event = row.count;
255
- if (row.costUsd !== null && row.costUsd > 0) {
256
- day.costUsd = addUsd(day.costUsd, row.costUsd);
257
- }
258
- }
259
- return [...byDate.values()];
260
- }
261
- async function readTaskExecutionHours(hourCount = 7 * 24, options = {}) {
262
- const nowMs = options.nowMs ?? Date.now();
263
- const end = new Date(nowMs);
264
- end.setUTCMinutes(0, 0, 0);
265
- const endMs = end.getTime() + 3599999;
266
- const startMs = end.getTime() - (hourCount - 1) * 36e5;
267
- const executionHour = sql2`to_char(to_timestamp(${juniorTaskExecutions.executedAtMs} / 1000.0) at time zone 'UTC', 'YYYY-MM-DD"T"HH24')`;
268
- const conversationCost = conversationUsageCostExpr(juniorConversations.usage);
269
- const rows = await getDb().select({
270
- count: count(),
271
- costUsd: sql2`SUM(${conversationCost})::double precision`,
272
- date: executionHour,
273
- kind: juniorTaskExecutions.kind
274
- }).from(juniorTaskExecutions).leftJoin(
275
- juniorConversations,
276
- eq(
277
- juniorConversations.conversationId,
278
- juniorTaskExecutions.conversationId
279
- )
280
- ).where(
281
- and(
282
- gte(juniorTaskExecutions.executedAtMs, startMs),
283
- lte(juniorTaskExecutions.executedAtMs, endMs),
284
- eq(juniorTaskExecutions.status, "completed")
285
- )
286
- ).groupBy(executionHour, juniorTaskExecutions.kind).orderBy(asc(executionHour), asc(juniorTaskExecutions.kind));
287
- const byHour = /* @__PURE__ */ new Map();
288
- for (let offset = 0; offset < hourCount; offset += 1) {
289
- const date = new Date(startMs + offset * 36e5).toISOString().slice(0, 13);
290
- byHour.set(date, emptyDay(date));
291
- }
292
- for (const row of rows) {
293
- const hour = byHour.get(row.date);
294
- if (!hour) continue;
295
- if (row.kind === "scheduled") hour.scheduled = row.count;
296
- else if (row.kind === "event") hour.event = row.count;
297
- if (row.costUsd !== null && row.costUsd > 0) {
298
- hour.costUsd = addUsd(hour.costUsd, row.costUsd);
299
- }
300
- }
301
- return [...byHour.values()];
302
- }
303
- async function readTaskExecutionByConversationId(args) {
304
- const namespace = args.namespace ?? "junior";
305
- const rows = await getDb().select({
306
- kind: juniorTaskExecutions.kind,
307
- taskId: juniorTaskExecutions.taskId
308
- }).from(juniorTaskExecutions).where(
309
- and(
310
- eq(juniorTaskExecutions.conversationId, args.conversationId),
311
- eq(juniorTaskExecutions.namespace, namespace),
312
- inArray(juniorTaskExecutions.kind, [...TASK_EXECUTION_TYPES])
313
- )
314
- ).orderBy(
315
- desc(juniorTaskExecutions.executedAtMs),
316
- desc(juniorTaskExecutions.executionId)
317
- ).limit(1);
318
- const row = rows[0];
319
- if (!row) return void 0;
320
- if (row.kind !== "scheduled" && row.kind !== "event") return void 0;
321
- return { kind: row.kind, taskId: row.taskId };
322
- }
323
- async function readTaskExecutions(args) {
324
- const namespace = args.namespace ?? "junior";
325
- const rows = await getDb().select({
326
- conversationId: juniorTaskExecutions.conversationId,
327
- durationMs: juniorConversations.durationMs,
328
- executedAtMs: juniorTaskExecutions.executedAtMs,
329
- executionId: juniorTaskExecutions.executionId,
330
- status: juniorTaskExecutions.status,
331
- title: juniorConversations.title,
332
- usage: juniorConversations.usage
333
- }).from(juniorTaskExecutions).leftJoin(
334
- juniorConversations,
335
- eq(
336
- juniorConversations.conversationId,
337
- juniorTaskExecutions.conversationId
338
- )
339
- ).where(
340
- and(
341
- eq(juniorTaskExecutions.kind, args.kind),
342
- eq(juniorTaskExecutions.namespace, namespace),
343
- eq(juniorTaskExecutions.taskId, args.taskId)
344
- )
345
- ).orderBy(
346
- desc(juniorTaskExecutions.executedAtMs),
347
- desc(juniorTaskExecutions.executionId)
348
- ).limit(args.limit);
349
- return rows.map((row) => mapTaskExecutionRecord(row));
350
- }
351
- async function readTaskRuns(args) {
352
- const tasks = args.tasks ?? [];
353
- const conversationIds = [
354
- ...new Set(
355
- (args.conversationIds ?? []).filter(
356
- (conversationId) => conversationId.trim().length > 0
357
- )
358
- )
359
- ];
360
- if (tasks.length === 0 && conversationIds.length === 0) return [];
361
- const namespace = args.namespace ?? "junior";
362
- const selectors = [
363
- ...tasks.map(
364
- (task) => and(
365
- eq(juniorTaskExecutions.kind, task.kind),
366
- eq(juniorTaskExecutions.taskId, task.taskId)
367
- )
368
- ),
369
- ...conversationIds.length > 0 ? [inArray(juniorTaskExecutions.conversationId, conversationIds)] : []
370
- ];
371
- const rows = await getDb().select({
372
- conversationId: juniorTaskExecutions.conversationId,
373
- durationMs: juniorConversations.durationMs,
374
- executedAtMs: juniorTaskExecutions.executedAtMs,
375
- executionId: juniorTaskExecutions.executionId,
376
- kind: juniorTaskExecutions.kind,
377
- status: juniorTaskExecutions.status,
378
- taskId: juniorTaskExecutions.taskId,
379
- title: juniorConversations.title,
380
- usage: juniorConversations.usage
381
- }).from(juniorTaskExecutions).leftJoin(
382
- juniorConversations,
383
- eq(
384
- juniorConversations.conversationId,
385
- juniorTaskExecutions.conversationId
386
- )
387
- ).where(and(eq(juniorTaskExecutions.namespace, namespace), or(...selectors))).orderBy(
388
- desc(juniorTaskExecutions.executedAtMs),
389
- desc(juniorTaskExecutions.executionId)
390
- ).limit(args.limit);
391
- return rows.flatMap((row) => {
392
- if (row.kind !== "scheduled" && row.kind !== "event") return [];
393
- return [
394
- {
395
- ...mapTaskExecutionRecord(row),
396
- kind: row.kind,
397
- taskId: row.taskId
398
- }
399
- ];
400
- });
401
- }
402
- function mapTaskExecutionRecord(row) {
403
- const title = row.title?.trim();
404
- const costUsd = agentTurnCostUsd(row.usage ?? void 0);
405
- const totalTokens = agentTurnTotalTokens(row.usage ?? void 0);
406
- const durationMs = typeof row.durationMs === "number" && Number.isFinite(row.durationMs) && row.durationMs > 0 ? row.durationMs : void 0;
407
- return {
408
- ...row.conversationId ? { conversationId: row.conversationId } : void 0,
409
- ...costUsd !== void 0 ? { costUsd } : void 0,
410
- ...durationMs !== void 0 ? { durationMs } : void 0,
411
- executedAt: new Date(row.executedAtMs).toISOString(),
412
- executionId: row.executionId,
413
- status: row.status,
414
- ...title ? { title } : void 0,
415
- ...totalTokens !== void 0 ? { totalTokens } : void 0
416
- };
417
- }
418
- async function readTaskExecutionStatusDays(args) {
419
- const dayCount = args.dayCount ?? 90;
420
- const namespace = args.namespace ?? "junior";
421
- const nowMs = args.nowMs ?? Date.now();
422
- const end = utcDate(nowMs);
423
- const endMs = Date.parse(`${end}T23:59:59.999Z`);
424
- const startMs = Date.parse(`${end}T00:00:00.000Z`) - (dayCount - 1) * 864e5;
425
- const executionDate = sql2`to_char(to_timestamp(${juniorTaskExecutions.executedAtMs} / 1000.0) at time zone 'UTC', 'YYYY-MM-DD')`;
426
- const rows = await getDb().select({
427
- count: count(),
428
- date: executionDate,
429
- status: juniorTaskExecutions.status
430
- }).from(juniorTaskExecutions).where(
431
- and(
432
- eq(juniorTaskExecutions.kind, args.kind),
433
- eq(juniorTaskExecutions.namespace, namespace),
434
- eq(juniorTaskExecutions.taskId, args.taskId),
435
- gte(juniorTaskExecutions.executedAtMs, startMs),
436
- lte(juniorTaskExecutions.executedAtMs, endMs),
437
- inArray(juniorTaskExecutions.status, [...TASK_EXECUTION_STATUSES])
438
- )
439
- ).groupBy(executionDate, juniorTaskExecutions.status).orderBy(asc(executionDate), asc(juniorTaskExecutions.status));
440
- const byDate = /* @__PURE__ */ new Map();
441
- for (let offset = 0; offset < dayCount; offset += 1) {
442
- const date = utcDate(startMs + offset * 864e5);
443
- byDate.set(date, emptyStatusDay(date));
444
- }
445
- for (const row of rows) {
446
- const day = byDate.get(row.date);
447
- if (!day) continue;
448
- if (row.status === "completed") day.completed = row.count;
449
- else if (row.status === "failed") day.failed = row.count;
450
- else if (row.status === "blocked") day.blocked = row.count;
451
- }
452
- return [...byDate.values()];
453
- }
454
- async function readTaskExecutionStatusHours(args) {
455
- const hourCount = args.hourCount ?? 7 * 24;
456
- const namespace = args.namespace ?? "junior";
457
- const nowMs = args.nowMs ?? Date.now();
458
- const end = new Date(nowMs);
459
- end.setUTCMinutes(0, 0, 0);
460
- const endMs = end.getTime() + 3599999;
461
- const startMs = end.getTime() - (hourCount - 1) * 36e5;
462
- const executionHour = sql2`to_char(to_timestamp(${juniorTaskExecutions.executedAtMs} / 1000.0) at time zone 'UTC', 'YYYY-MM-DD"T"HH24')`;
463
- const rows = await getDb().select({
464
- count: count(),
465
- date: executionHour,
466
- status: juniorTaskExecutions.status
467
- }).from(juniorTaskExecutions).where(
468
- and(
469
- eq(juniorTaskExecutions.kind, args.kind),
470
- eq(juniorTaskExecutions.namespace, namespace),
471
- eq(juniorTaskExecutions.taskId, args.taskId),
472
- gte(juniorTaskExecutions.executedAtMs, startMs),
473
- lte(juniorTaskExecutions.executedAtMs, endMs),
474
- inArray(juniorTaskExecutions.status, [...TASK_EXECUTION_STATUSES])
475
- )
476
- ).groupBy(executionHour, juniorTaskExecutions.status).orderBy(asc(executionHour), asc(juniorTaskExecutions.status));
477
- const byHour = /* @__PURE__ */ new Map();
478
- for (let offset = 0; offset < hourCount; offset += 1) {
479
- const date = new Date(startMs + offset * 36e5).toISOString().slice(0, 13);
480
- byHour.set(date, emptyStatusDay(date));
481
- }
482
- for (const row of rows) {
483
- const hour = byHour.get(row.date);
484
- if (!hour) continue;
485
- if (row.status === "completed") hour.completed = row.count;
486
- else if (row.status === "failed") hour.failed = row.count;
487
- else if (row.status === "blocked") hour.blocked = row.count;
488
- }
489
- return [...byHour.values()];
490
- }
491
-
492
- export {
493
- conversationAggregateColumns,
494
- conversationRangeColumns,
495
- conversationActiveDaysColumn,
496
- emptyTaskRunWindows,
497
- recordTaskExecution,
498
- readTaskExecutionSummaries,
499
- readTaskExecutionDays,
500
- readTaskExecutionHours,
501
- readTaskExecutionByConversationId,
502
- readTaskExecutions,
503
- readTaskRuns,
504
- readTaskExecutionStatusDays,
505
- readTaskExecutionStatusHours
506
- };
@@ -1,70 +0,0 @@
1
- // src/chat/local/oauth-relay.ts
2
- import { randomBytes } from "crypto";
3
- import { jwtVerify, SignJWT } from "jose";
4
- import { z } from "zod";
5
- var LOCAL_OAUTH_STATE_PREFIX = "jr-local";
6
- var LOCAL_OAUTH_TOKEN_CONTEXT = "junior.local-oauth-relay.v1";
7
- var LOCAL_OAUTH_TOKEN_TTL = "10m";
8
- var localOAuthRelayPayloadSchema = z.object({
9
- aud: z.literal(LOCAL_OAUTH_TOKEN_CONTEXT),
10
- exp: z.number().int(),
11
- iss: z.literal(LOCAL_OAUTH_TOKEN_CONTEXT),
12
- jti: z.string().min(1),
13
- port: z.number().int().min(1).max(65535)
14
- }).strict();
15
- function relayKey() {
16
- const secret = process.env.JUNIOR_SECRET?.trim();
17
- if (!secret) {
18
- throw new Error("Local OAuth requires JUNIOR_SECRET");
19
- }
20
- return new TextEncoder().encode(secret);
21
- }
22
- async function createLocalOAuthState(port) {
23
- if (!Number.isSafeInteger(port) || port < 1 || port > 65535) {
24
- throw new Error("Local OAuth callback port is invalid");
25
- }
26
- const token = await new SignJWT({ port }).setProtectedHeader({ alg: "HS256" }).setIssuer(LOCAL_OAUTH_TOKEN_CONTEXT).setAudience(LOCAL_OAUTH_TOKEN_CONTEXT).setJti(randomBytes(24).toString("base64url")).setExpirationTime(LOCAL_OAUTH_TOKEN_TTL).sign(relayKey());
27
- return `${LOCAL_OAUTH_STATE_PREFIX}.${token}`;
28
- }
29
- async function localOAuthRelayPort(state) {
30
- const prefix = `${LOCAL_OAUTH_STATE_PREFIX}.`;
31
- if (!state.startsWith(prefix)) {
32
- return void 0;
33
- }
34
- try {
35
- const { payload } = await jwtVerify(
36
- state.slice(prefix.length),
37
- relayKey(),
38
- {
39
- algorithms: ["HS256"],
40
- issuer: LOCAL_OAUTH_TOKEN_CONTEXT,
41
- audience: LOCAL_OAUTH_TOKEN_CONTEXT
42
- }
43
- );
44
- const parsed = localOAuthRelayPayloadSchema.safeParse(payload);
45
- return parsed.success ? parsed.data.port : void 0;
46
- } catch {
47
- return void 0;
48
- }
49
- }
50
- async function relayLocalOAuthCallback(request) {
51
- const url = new URL(request.url);
52
- if (url.searchParams.get("jr_local_relay") === "complete") {
53
- return void 0;
54
- }
55
- const state = url.searchParams.get("state");
56
- const port = state ? await localOAuthRelayPort(state) : void 0;
57
- if (!port) {
58
- return void 0;
59
- }
60
- url.protocol = "http:";
61
- url.hostname = "127.0.0.1";
62
- url.port = String(port);
63
- url.searchParams.set("jr_local_relay", "complete");
64
- return Response.redirect(url, 302);
65
- }
66
-
67
- export {
68
- createLocalOAuthState,
69
- relayLocalOAuthCallback
70
- };