@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
@@ -0,0 +1,5 @@
1
+ import "./store-C5qxF2ac.js";
2
+ import { z } from "zod";
3
+ import "drizzle-orm/pg-core";
4
+ import "drizzle-orm/migrator";
5
+ import "drizzle-orm/pg-core/session";
@@ -0,0 +1,29 @@
1
+ import { z } from "zod";
2
+ import { index, jsonb, pgTable, text, timestamp, uniqueIndex } from "drizzle-orm/pg-core";
3
+ //#region src/db/schema/timestamps.ts
4
+ const timestamptz = (name) => timestamp(name, { withTimezone: true });
5
+ //#endregion
6
+ //#region src/db/schema/destinations.ts
7
+ const juniorDestinationKindSchema = z.enum([
8
+ "channel",
9
+ "dm",
10
+ "group",
11
+ "local_conversation",
12
+ "thread",
13
+ "web_session"
14
+ ]);
15
+ const juniorDestinations = pgTable("junior_destinations", {
16
+ id: text("id").primaryKey(),
17
+ provider: text("provider").notNull(),
18
+ providerTenantId: text("provider_tenant_id").notNull().default(""),
19
+ providerDestinationId: text("provider_destination_id").notNull(),
20
+ kind: text("kind").$type().notNull(),
21
+ parentDestinationId: text("parent_destination_id"),
22
+ displayName: text("display_name"),
23
+ visibility: text("visibility").$type().notNull().default("unknown"),
24
+ metadata: jsonb("metadata_json"),
25
+ createdAt: timestamptz("created_at").notNull(),
26
+ updatedAt: timestamptz("updated_at").notNull()
27
+ }, (table) => [uniqueIndex("junior_destinations_provider_destination_uidx").on(table.provider, table.providerTenantId, table.providerDestinationId), index("junior_destinations_provider_kind_idx").on(table.provider, table.kind)]);
28
+ //#endregion
29
+ export { juniorDestinations as n, timestamptz as r, juniorDestinationKindSchema as t };
@@ -0,0 +1,373 @@
1
+ import { f as logWarn } from "./logging-BzAk1S_s.js";
2
+ import { Et as getDb } from "./agent-hooks-Bbcp9e33.js";
3
+ import { C as juniorConversations, s as juniorTaskExecutions } from "./executor-DcMSlI5c.js";
4
+ import { n as agentTurnCostUsd, r as agentTurnTotalTokens } from "./usage-D3EbSO7w.js";
5
+ import { and, asc, count, desc, eq, gte, inArray, lte, max, or, sql } from "drizzle-orm";
6
+ //#region src/api/conversations/aggregate.ts
7
+ function usageTokenValue(source, field) {
8
+ return sql`CASE
9
+ WHEN ${source.usage}->>${field} IS NOT NULL
10
+ THEN (${source.usage}->>${field})::double precision
11
+ ELSE NULL
12
+ END`;
13
+ }
14
+ function tokenValue(source) {
15
+ return sql`
16
+ CASE
17
+ WHEN COALESCE(
18
+ ${source.usage}->>'inputTokens',
19
+ ${source.usage}->>'outputTokens',
20
+ ${source.usage}->>'cachedInputTokens',
21
+ ${source.usage}->>'cacheCreationTokens'
22
+ ) IS NOT NULL
23
+ THEN COALESCE((${source.usage}->>'inputTokens')::double precision, 0)
24
+ + COALESCE((${source.usage}->>'outputTokens')::double precision, 0)
25
+ + COALESCE((${source.usage}->>'cachedInputTokens')::double precision, 0)
26
+ + COALESCE((${source.usage}->>'cacheCreationTokens')::double precision, 0)
27
+ WHEN ${source.usage}->>'totalTokens' IS NOT NULL
28
+ THEN (${source.usage}->>'totalTokens')::double precision
29
+ ELSE NULL
30
+ END
31
+ `;
32
+ }
33
+ function costValue(source) {
34
+ return conversationUsageCostExpr(source.usage);
35
+ }
36
+ /** Read one conversation row's usage cost as a SQL expression. */
37
+ function conversationUsageCostExpr(usage) {
38
+ return sql`
39
+ CASE
40
+ WHEN ${usage}->'cost'->>'total' IS NOT NULL
41
+ THEN (${usage}->'cost'->>'total')::double precision
42
+ WHEN COALESCE(
43
+ ${usage}->'cost'->>'input',
44
+ ${usage}->'cost'->>'output',
45
+ ${usage}->'cost'->>'cacheRead',
46
+ ${usage}->'cost'->>'cacheWrite'
47
+ ) IS NOT NULL
48
+ THEN COALESCE((${usage}->'cost'->>'input')::double precision, 0)
49
+ + COALESCE((${usage}->'cost'->>'output')::double precision, 0)
50
+ + COALESCE((${usage}->'cost'->>'cacheRead')::double precision, 0)
51
+ + COALESCE((${usage}->'cost'->>'cacheWrite')::double precision, 0)
52
+ ELSE NULL
53
+ END
54
+ `;
55
+ }
56
+ /** Select complete conversation metrics inside the database instead of materializing source rows. */
57
+ function conversationAggregateColumns(sources) {
58
+ const metrics = sources?.metrics ?? juniorConversations;
59
+ const roots = sources?.roots ?? juniorConversations;
60
+ const conversationCount = sources ? sql`COUNT(DISTINCT ${roots.conversationId})` : sql`COUNT(*)`;
61
+ return {
62
+ active: sql`${conversationCount} FILTER (
63
+ WHERE ${roots.executionStatus} NOT IN ('idle', 'failed')
64
+ )::integer`,
65
+ conversations: sql`${conversationCount}::integer`,
66
+ cachedInputTokens: sql`SUM(${usageTokenValue(metrics, "cachedInputTokens")})::double precision`,
67
+ costUsd: sql`SUM(${costValue(metrics)})::double precision`,
68
+ durationMs: sql`COALESCE(SUM(${metrics.durationMs}), 0)::double precision`,
69
+ failed: sql`${conversationCount} FILTER (
70
+ WHERE ${roots.executionStatus} = 'failed'
71
+ )::integer`,
72
+ inputTokens: sql`SUM(${usageTokenValue(metrics, "inputTokens")})::double precision`,
73
+ tokens: sql`SUM(${tokenValue(metrics)})::double precision`
74
+ };
75
+ }
76
+ /** Select the complete first/last activity range for a grouped conversation aggregate. */
77
+ function conversationRangeColumns() {
78
+ return {
79
+ firstSeenAt: sql`MIN(${juniorConversations.createdAt})`.mapWith(juniorConversations.createdAt),
80
+ lastSeenAt: sql`MAX(${juniorConversations.lastActivityAt})`.mapWith(juniorConversations.lastActivityAt)
81
+ };
82
+ }
83
+ /** Count distinct UTC activity dates without loading conversation timestamps into the app. */
84
+ function conversationActiveDaysColumn() {
85
+ return sql`COUNT(DISTINCT (${juniorConversations.lastActivityAt} AT TIME ZONE 'UTC')::date)::integer`;
86
+ }
87
+ //#endregion
88
+ //#region src/chat/tasks/execution-stats.ts
89
+ const TASK_EXECUTION_TYPES = ["scheduled", "event"];
90
+ const TASK_EXECUTION_STATUSES = [
91
+ "blocked",
92
+ "completed",
93
+ "failed"
94
+ ];
95
+ function addUsd(current, next) {
96
+ return Math.round((current + next) * 0xe8d4a51000) / 0xe8d4a51000;
97
+ }
98
+ const EMPTY_RUN_WINDOWS = {
99
+ 1: 0,
100
+ 7: 0,
101
+ 30: 0,
102
+ 90: 0
103
+ };
104
+ /** Empty run windows for tasks with no execution history. */
105
+ function emptyTaskRunWindows() {
106
+ return { ...EMPTY_RUN_WINDOWS };
107
+ }
108
+ function utcDate(nowMs) {
109
+ return new Date(nowMs).toISOString().slice(0, 10);
110
+ }
111
+ function emptyDay(date) {
112
+ return {
113
+ costUsd: 0,
114
+ date,
115
+ event: 0,
116
+ scheduled: 0
117
+ };
118
+ }
119
+ function emptyStatusDay(date) {
120
+ return {
121
+ blocked: 0,
122
+ completed: 0,
123
+ date,
124
+ failed: 0
125
+ };
126
+ }
127
+ /** Record one terminal task execution and its durable conversation when present. */
128
+ async function recordTaskExecution(type, taskId, options) {
129
+ const namespace = options.namespace ?? "junior";
130
+ const nowMs = options.nowMs ?? Date.now();
131
+ const status = options.status ?? "completed";
132
+ try {
133
+ await getDb().insert(juniorTaskExecutions).values({
134
+ ...options.conversationId ? { conversationId: options.conversationId } : void 0,
135
+ executedAtMs: nowMs,
136
+ executionId: options.executionId,
137
+ kind: type,
138
+ namespace,
139
+ status,
140
+ taskId
141
+ }).onConflictDoNothing({ target: [
142
+ juniorTaskExecutions.kind,
143
+ juniorTaskExecutions.namespace,
144
+ juniorTaskExecutions.executionId
145
+ ] });
146
+ } catch (error) {
147
+ logWarn("task.execution.stat_failed", {
148
+ error,
149
+ "app.task.execution.id": options.executionId,
150
+ "app.task.execution.namespace": namespace,
151
+ "app.task.execution.status": status,
152
+ "app.task.execution.task_id": taskId,
153
+ "app.task.execution.type": type
154
+ });
155
+ }
156
+ }
157
+ /** Load usage analytics for all tasks of one type and namespace. */
158
+ async function readTaskExecutionSummaries(type, namespace, options = {}) {
159
+ const nowMs = options.nowMs ?? Date.now();
160
+ const oneDayAgoMs = nowMs - 864e5;
161
+ const sevenDaysAgoMs = nowMs - 6048e5;
162
+ const thirtyDaysAgoMs = nowMs - 2592e6;
163
+ const ninetyDaysAgoMs = nowMs - 7776e6;
164
+ const db = getDb();
165
+ const latest = db.selectDistinctOn([juniorTaskExecutions.taskId], {
166
+ conversationId: juniorTaskExecutions.conversationId,
167
+ taskId: juniorTaskExecutions.taskId
168
+ }).from(juniorTaskExecutions).where(and(eq(juniorTaskExecutions.kind, type), eq(juniorTaskExecutions.namespace, namespace))).orderBy(juniorTaskExecutions.taskId, desc(juniorTaskExecutions.executedAtMs), desc(juniorTaskExecutions.executionId)).as("latest_task_execution");
169
+ const rows = await db.select({
170
+ lastConversationId: latest.conversationId,
171
+ lastExecutedAtMs: max(juniorTaskExecutions.executedAtMs),
172
+ runsLast1Day: sql`count(*) filter (where ${juniorTaskExecutions.executedAtMs} >= ${oneDayAgoMs})::int`,
173
+ runsLast7Days: sql`count(*) filter (where ${juniorTaskExecutions.executedAtMs} >= ${sevenDaysAgoMs})::int`,
174
+ runsLast30Days: sql`count(*) filter (where ${juniorTaskExecutions.executedAtMs} >= ${thirtyDaysAgoMs})::int`,
175
+ runsLast90Days: sql`count(*) filter (where ${juniorTaskExecutions.executedAtMs} >= ${ninetyDaysAgoMs})::int`,
176
+ taskId: juniorTaskExecutions.taskId,
177
+ totalRuns: sql`count(*)::int`
178
+ }).from(juniorTaskExecutions).innerJoin(latest, eq(latest.taskId, juniorTaskExecutions.taskId)).where(and(eq(juniorTaskExecutions.kind, type), eq(juniorTaskExecutions.namespace, namespace))).groupBy(juniorTaskExecutions.taskId, latest.conversationId);
179
+ return new Map(rows.map((row) => [row.taskId, {
180
+ ...row.lastConversationId ? { lastConversationId: row.lastConversationId } : void 0,
181
+ ...row.lastExecutedAtMs !== null ? { lastExecutedAtMs: row.lastExecutedAtMs } : void 0,
182
+ runs: {
183
+ 1: row.runsLast1Day,
184
+ 7: row.runsLast7Days,
185
+ 30: row.runsLast30Days,
186
+ 90: row.runsLast90Days
187
+ },
188
+ totalRuns: row.totalRuns
189
+ }]));
190
+ }
191
+ /** Load a fixed trailing window of completed executions stacked by task type. */
192
+ async function readTaskExecutionDays(dayCount = 90, options = {}) {
193
+ const end = utcDate(options.nowMs ?? Date.now());
194
+ const endMs = Date.parse(`${end}T23:59:59.999Z`);
195
+ const startMs = Date.parse(`${end}T00:00:00.000Z`) - (dayCount - 1) * 864e5;
196
+ const executionDate = sql`to_char(to_timestamp(${juniorTaskExecutions.executedAtMs} / 1000.0) at time zone 'UTC', 'YYYY-MM-DD')`;
197
+ const conversationCost = conversationUsageCostExpr(juniorConversations.usage);
198
+ const rows = await getDb().select({
199
+ count: count(),
200
+ costUsd: sql`SUM(${conversationCost})::double precision`,
201
+ date: executionDate,
202
+ kind: juniorTaskExecutions.kind
203
+ }).from(juniorTaskExecutions).leftJoin(juniorConversations, eq(juniorConversations.conversationId, juniorTaskExecutions.conversationId)).where(and(gte(juniorTaskExecutions.executedAtMs, startMs), lte(juniorTaskExecutions.executedAtMs, endMs), eq(juniorTaskExecutions.status, "completed"))).groupBy(executionDate, juniorTaskExecutions.kind).orderBy(asc(executionDate), asc(juniorTaskExecutions.kind));
204
+ const byDate = /* @__PURE__ */ new Map();
205
+ for (let offset = 0; offset < dayCount; offset += 1) {
206
+ const date = utcDate(startMs + offset * 864e5);
207
+ byDate.set(date, emptyDay(date));
208
+ }
209
+ for (const row of rows) {
210
+ const day = byDate.get(row.date);
211
+ if (!day) continue;
212
+ if (row.kind === "scheduled") day.scheduled = row.count;
213
+ else if (row.kind === "event") day.event = row.count;
214
+ if (row.costUsd !== null && row.costUsd > 0) day.costUsd = addUsd(day.costUsd, row.costUsd);
215
+ }
216
+ return [...byDate.values()];
217
+ }
218
+ /** Load a fixed trailing window of completed executions stacked by hour. */
219
+ async function readTaskExecutionHours(hourCount = 168, options = {}) {
220
+ const nowMs = options.nowMs ?? Date.now();
221
+ const end = new Date(nowMs);
222
+ end.setUTCMinutes(0, 0, 0);
223
+ const endMs = end.getTime() + 3599999;
224
+ const startMs = end.getTime() - (hourCount - 1) * 36e5;
225
+ const executionHour = sql`to_char(to_timestamp(${juniorTaskExecutions.executedAtMs} / 1000.0) at time zone 'UTC', 'YYYY-MM-DD"T"HH24')`;
226
+ const conversationCost = conversationUsageCostExpr(juniorConversations.usage);
227
+ const rows = await getDb().select({
228
+ count: count(),
229
+ costUsd: sql`SUM(${conversationCost})::double precision`,
230
+ date: executionHour,
231
+ kind: juniorTaskExecutions.kind
232
+ }).from(juniorTaskExecutions).leftJoin(juniorConversations, eq(juniorConversations.conversationId, juniorTaskExecutions.conversationId)).where(and(gte(juniorTaskExecutions.executedAtMs, startMs), lte(juniorTaskExecutions.executedAtMs, endMs), eq(juniorTaskExecutions.status, "completed"))).groupBy(executionHour, juniorTaskExecutions.kind).orderBy(asc(executionHour), asc(juniorTaskExecutions.kind));
233
+ const byHour = /* @__PURE__ */ new Map();
234
+ for (let offset = 0; offset < hourCount; offset += 1) {
235
+ const date = new Date(startMs + offset * 36e5).toISOString().slice(0, 13);
236
+ byHour.set(date, emptyDay(date));
237
+ }
238
+ for (const row of rows) {
239
+ const hour = byHour.get(row.date);
240
+ if (!hour) continue;
241
+ if (row.kind === "scheduled") hour.scheduled = row.count;
242
+ else if (row.kind === "event") hour.event = row.count;
243
+ if (row.costUsd !== null && row.costUsd > 0) hour.costUsd = addUsd(hour.costUsd, row.costUsd);
244
+ }
245
+ return [...byHour.values()];
246
+ }
247
+ /** Load the newest terminal task execution linked to one conversation, if any. */
248
+ async function readTaskExecutionByConversationId(args) {
249
+ const namespace = args.namespace ?? "junior";
250
+ const row = (await getDb().select({
251
+ kind: juniorTaskExecutions.kind,
252
+ taskId: juniorTaskExecutions.taskId
253
+ }).from(juniorTaskExecutions).where(and(eq(juniorTaskExecutions.conversationId, args.conversationId), eq(juniorTaskExecutions.namespace, namespace), inArray(juniorTaskExecutions.kind, [...TASK_EXECUTION_TYPES]))).orderBy(desc(juniorTaskExecutions.executedAtMs), desc(juniorTaskExecutions.executionId)).limit(1))[0];
254
+ if (!row) return void 0;
255
+ if (row.kind !== "scheduled" && row.kind !== "event") return void 0;
256
+ return {
257
+ kind: row.kind,
258
+ taskId: row.taskId
259
+ };
260
+ }
261
+ /** Load newest-first executions for one task, with conversation titles when present. */
262
+ async function readTaskExecutions(args) {
263
+ const namespace = args.namespace ?? "junior";
264
+ return (await getDb().select({
265
+ conversationId: juniorTaskExecutions.conversationId,
266
+ durationMs: juniorConversations.durationMs,
267
+ executedAtMs: juniorTaskExecutions.executedAtMs,
268
+ executionId: juniorTaskExecutions.executionId,
269
+ status: juniorTaskExecutions.status,
270
+ title: juniorConversations.title,
271
+ usage: juniorConversations.usage
272
+ }).from(juniorTaskExecutions).leftJoin(juniorConversations, eq(juniorConversations.conversationId, juniorTaskExecutions.conversationId)).where(and(eq(juniorTaskExecutions.kind, args.kind), eq(juniorTaskExecutions.namespace, namespace), eq(juniorTaskExecutions.taskId, args.taskId))).orderBy(desc(juniorTaskExecutions.executedAtMs), desc(juniorTaskExecutions.executionId)).limit(args.limit)).map((row) => mapTaskExecutionRecord(row));
273
+ }
274
+ /** Load newest-first executions for the supplied viewer-visible tasks. */
275
+ async function readTaskRuns(args) {
276
+ const tasks = args.tasks ?? [];
277
+ const conversationIds = [...new Set((args.conversationIds ?? []).filter((conversationId) => conversationId.trim().length > 0))];
278
+ if (tasks.length === 0 && conversationIds.length === 0) return [];
279
+ const namespace = args.namespace ?? "junior";
280
+ const selectors = [...tasks.map((task) => and(eq(juniorTaskExecutions.kind, task.kind), eq(juniorTaskExecutions.taskId, task.taskId))), ...conversationIds.length > 0 ? [inArray(juniorTaskExecutions.conversationId, conversationIds)] : []];
281
+ return (await getDb().select({
282
+ conversationId: juniorTaskExecutions.conversationId,
283
+ durationMs: juniorConversations.durationMs,
284
+ executedAtMs: juniorTaskExecutions.executedAtMs,
285
+ executionId: juniorTaskExecutions.executionId,
286
+ kind: juniorTaskExecutions.kind,
287
+ status: juniorTaskExecutions.status,
288
+ taskId: juniorTaskExecutions.taskId,
289
+ title: juniorConversations.title,
290
+ usage: juniorConversations.usage
291
+ }).from(juniorTaskExecutions).leftJoin(juniorConversations, eq(juniorConversations.conversationId, juniorTaskExecutions.conversationId)).where(and(eq(juniorTaskExecutions.namespace, namespace), or(...selectors))).orderBy(desc(juniorTaskExecutions.executedAtMs), desc(juniorTaskExecutions.executionId)).limit(args.limit)).flatMap((row) => {
292
+ if (row.kind !== "scheduled" && row.kind !== "event") return [];
293
+ return [{
294
+ ...mapTaskExecutionRecord(row),
295
+ kind: row.kind,
296
+ taskId: row.taskId
297
+ }];
298
+ });
299
+ }
300
+ function mapTaskExecutionRecord(row) {
301
+ const title = row.title?.trim();
302
+ const costUsd = agentTurnCostUsd(row.usage ?? void 0);
303
+ const totalTokens = agentTurnTotalTokens(row.usage ?? void 0);
304
+ const durationMs = typeof row.durationMs === "number" && Number.isFinite(row.durationMs) && row.durationMs > 0 ? row.durationMs : void 0;
305
+ return {
306
+ ...row.conversationId ? { conversationId: row.conversationId } : void 0,
307
+ ...costUsd !== void 0 ? { costUsd } : void 0,
308
+ ...durationMs !== void 0 ? { durationMs } : void 0,
309
+ executedAt: new Date(row.executedAtMs).toISOString(),
310
+ executionId: row.executionId,
311
+ status: row.status,
312
+ ...title ? { title } : void 0,
313
+ ...totalTokens !== void 0 ? { totalTokens } : void 0
314
+ };
315
+ }
316
+ /** Load a fixed trailing window of terminal executions for one task by status. */
317
+ async function readTaskExecutionStatusDays(args) {
318
+ const dayCount = args.dayCount ?? 90;
319
+ const namespace = args.namespace ?? "junior";
320
+ const end = utcDate(args.nowMs ?? Date.now());
321
+ const endMs = Date.parse(`${end}T23:59:59.999Z`);
322
+ const startMs = Date.parse(`${end}T00:00:00.000Z`) - (dayCount - 1) * 864e5;
323
+ const executionDate = sql`to_char(to_timestamp(${juniorTaskExecutions.executedAtMs} / 1000.0) at time zone 'UTC', 'YYYY-MM-DD')`;
324
+ const rows = await getDb().select({
325
+ count: count(),
326
+ date: executionDate,
327
+ status: juniorTaskExecutions.status
328
+ }).from(juniorTaskExecutions).where(and(eq(juniorTaskExecutions.kind, args.kind), eq(juniorTaskExecutions.namespace, namespace), eq(juniorTaskExecutions.taskId, args.taskId), gte(juniorTaskExecutions.executedAtMs, startMs), lte(juniorTaskExecutions.executedAtMs, endMs), inArray(juniorTaskExecutions.status, [...TASK_EXECUTION_STATUSES]))).groupBy(executionDate, juniorTaskExecutions.status).orderBy(asc(executionDate), asc(juniorTaskExecutions.status));
329
+ const byDate = /* @__PURE__ */ new Map();
330
+ for (let offset = 0; offset < dayCount; offset += 1) {
331
+ const date = utcDate(startMs + offset * 864e5);
332
+ byDate.set(date, emptyStatusDay(date));
333
+ }
334
+ for (const row of rows) {
335
+ const day = byDate.get(row.date);
336
+ if (!day) continue;
337
+ if (row.status === "completed") day.completed = row.count;
338
+ else if (row.status === "failed") day.failed = row.count;
339
+ else if (row.status === "blocked") day.blocked = row.count;
340
+ }
341
+ return [...byDate.values()];
342
+ }
343
+ /** Load a fixed trailing window of terminal executions for one task by hour. */
344
+ async function readTaskExecutionStatusHours(args) {
345
+ const hourCount = args.hourCount ?? 168;
346
+ const namespace = args.namespace ?? "junior";
347
+ const nowMs = args.nowMs ?? Date.now();
348
+ const end = new Date(nowMs);
349
+ end.setUTCMinutes(0, 0, 0);
350
+ const endMs = end.getTime() + 3599999;
351
+ const startMs = end.getTime() - (hourCount - 1) * 36e5;
352
+ const executionHour = sql`to_char(to_timestamp(${juniorTaskExecutions.executedAtMs} / 1000.0) at time zone 'UTC', 'YYYY-MM-DD"T"HH24')`;
353
+ const rows = await getDb().select({
354
+ count: count(),
355
+ date: executionHour,
356
+ status: juniorTaskExecutions.status
357
+ }).from(juniorTaskExecutions).where(and(eq(juniorTaskExecutions.kind, args.kind), eq(juniorTaskExecutions.namespace, namespace), eq(juniorTaskExecutions.taskId, args.taskId), gte(juniorTaskExecutions.executedAtMs, startMs), lte(juniorTaskExecutions.executedAtMs, endMs), inArray(juniorTaskExecutions.status, [...TASK_EXECUTION_STATUSES]))).groupBy(executionHour, juniorTaskExecutions.status).orderBy(asc(executionHour), asc(juniorTaskExecutions.status));
358
+ const byHour = /* @__PURE__ */ new Map();
359
+ for (let offset = 0; offset < hourCount; offset += 1) {
360
+ const date = new Date(startMs + offset * 36e5).toISOString().slice(0, 13);
361
+ byHour.set(date, emptyStatusDay(date));
362
+ }
363
+ for (const row of rows) {
364
+ const hour = byHour.get(row.date);
365
+ if (!hour) continue;
366
+ if (row.status === "completed") hour.completed = row.count;
367
+ else if (row.status === "failed") hour.failed = row.count;
368
+ else if (row.status === "blocked") hour.blocked = row.count;
369
+ }
370
+ return [...byHour.values()];
371
+ }
372
+ //#endregion
373
+ export { readTaskExecutionStatusDays as a, readTaskExecutions as c, conversationActiveDaysColumn as d, conversationAggregateColumns as f, readTaskExecutionHours as i, readTaskRuns as l, readTaskExecutionByConversationId as n, readTaskExecutionStatusHours as o, conversationRangeColumns as p, readTaskExecutionDays as r, readTaskExecutionSummaries as s, emptyTaskRunWindows as t, recordTaskExecution as u };