@sentry/junior 0.225.0 → 0.227.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 (65) hide show
  1. package/dist/{agent-hooks-CRuRcOg9.js → agent-hooks-bEwEJhlg.js} +231 -17
  2. package/dist/{agent-runner-Cad1RtWn.js → agent-runner-BGDSjciH.js} +2899 -159
  3. package/dist/api/schema.d.ts +417 -15
  4. package/dist/api/schema.js +4 -4
  5. package/dist/api.js +57 -32
  6. package/dist/{app-BbSD6EtD.d.ts → app-CjRIKZb5.d.ts} +1 -1
  7. package/dist/app.d.ts +1 -1
  8. package/dist/app.js +971 -7685
  9. package/dist/{briefs-BtnkPWT5.js → briefs-BkM_ZW4B.js} +4 -4
  10. package/dist/{catalog-runtime-pv4grNNb.js → catalog-runtime-Cw9V2jpn.js} +1 -1
  11. package/dist/{checkpoint-6fkAdB3g.js → checkpoint-oZYD3-Ar.js} +77 -11
  12. package/dist/cli/chat.js +13 -13
  13. package/dist/cli/check.js +3 -3
  14. package/dist/cli/main.js +1 -1
  15. package/dist/cli/plugins.js +3 -3
  16. package/dist/cli/snapshot-create.js +3 -3
  17. package/dist/cli/upgrade.js +3 -3
  18. package/dist/{client-ihmkx60d.js → client-Pcxo3lGn.js} +2 -2
  19. package/dist/{config-DMg679BW.js → config-CYvEow1F.js} +2 -2
  20. package/dist/{context-Bplcgypl.js → context-0Et9iVSB.js} +1 -1
  21. package/dist/{conversation-Bygi39Xj.js → conversation-BnhOMfEB.js} +113 -25
  22. package/dist/{conversation-privacy-ZYy05Y3q.js → conversation-privacy-hQmyZbOC.js} +1 -1
  23. package/dist/{credential-sync-DCB2SwnQ.js → credential-sync-CUGbiiCM.js} +15 -135
  24. package/dist/{executor-B9R4cHte.js → executor-BXMlFrV6.js} +1 -1
  25. package/dist/history-nukv1YN8.d.ts +127 -0
  26. package/dist/images-8siTAUNW.js +82 -0
  27. package/dist/instrumentation.js +2 -2
  28. package/dist/{vercel-queue-DIkVcfK4.js → job-queue-AI0_QAgc.js} +61 -2
  29. package/dist/{logging-CcTvYQ8A.js → logging-BPBx6WF-.js} +1 -1
  30. package/dist/nitro.d.ts +1 -1
  31. package/dist/nitro.js +3 -4
  32. package/dist/{oauth-authorization-BS4vPJmu.js → oauth-authorization-Cq1GaLIP.js} +1 -1
  33. package/dist/{oauth-callback-server-DnlQsGBJ.js → oauth-callback-server-CnF03VYh.js} +2 -2
  34. package/dist/pending-auth-CHUjr_6d.js +59 -0
  35. package/dist/{profile-CV97YuiL.js → profile-upzC-wN1.js} +4 -4
  36. package/dist/{prompt-CL8zxsmm.js → prompt-CZIQcPHy.js} +1 -1
  37. package/dist/{registry-C8I4IejN.js → registry-DM5aMhjm.js} +2 -2
  38. package/dist/{resolve-DXVAzYa3.js → resolve-sF6Lg7Ay.js} +2 -2
  39. package/dist/{runner-Die1RJ_z.js → runner-Bu2wYpK8.js} +10 -10
  40. package/dist/{sandbox-egress-signals-BZepyVh1.js → sandbox-egress-signals-Dgerhizb.js} +1 -1
  41. package/dist/{schema-BE4uso4i.js → schema-BSiwcvjm.js} +2 -2
  42. package/dist/{skills-DUcDEgDI.js → skills-CAI5s___.js} +2 -2
  43. package/dist/{spawn-o15i3tJu.js → spawn-DRK9TBgY.js} +2 -2
  44. package/dist/{task-queue-D3PLY59C.js → task-queue-iuDAqfZg.js} +3 -4
  45. package/dist/{task-runner-BMl2aM2v.js → task-runner-S3QtH38c.js} +381 -12
  46. package/dist/{thread-state-CAR6gdAm.js → thread-state-C_arVuaN.js} +5 -5
  47. package/dist/{turn-failure-response-CZyoUMkD.js → turn-failure-response-DarwGYgC.js} +9 -10
  48. package/dist/{turn-lifecycle-DPDHKi2U.js → turn-lifecycle-CdiIejXH.js} +1 -1
  49. package/dist/{turn-session-routing-Jkmmxpp-.js → turn-session-routing-DyLGd_wU.js} +1 -1
  50. package/dist/{validation-BcGGxOa6.js → validation-BMig74Zp.js} +1 -1
  51. package/dist/{version-DYcuOFQb.js → version-lhQSfLjx.js} +1 -1
  52. package/dist/version.js +1 -1
  53. package/dist/web-authorization-r2lKYKJ2.js +162 -0
  54. package/dist/web-input-BU-Fu7iq.js +7784 -0
  55. package/dist/{reporting-window-DbUqng0P.js → web-message-id-xPI_EFSC.js} +11 -1
  56. package/dist/{work-Bm90pR9P.js → work-B9koS8sW.js} +7 -8
  57. package/dist/{worker-BvHr6JhE.js → worker-C_iJSRgG.js} +5 -6
  58. package/package.json +5 -4
  59. package/dist/execution-stats-CR9CYpyj.js +0 -373
  60. package/dist/history-yaSjGMD_.d.ts +0 -65
  61. package/dist/job-queue-D2SiTrnt.js +0 -63
  62. package/dist/short-title-3wYH3ipl.js +0 -71
  63. package/dist/stats-DawHjcTw.js +0 -2758
  64. package/dist/web-authorization-B09B8A8R.js +0 -38
  65. package/dist/web-input-CGE58TpK.js +0 -899
@@ -226,4 +226,14 @@ function sumUtcHoursIntoSixHours(args) {
226
226
  });
227
227
  }
228
228
  //#endregion
229
- export { skillReportsSchema as S, pluginPackageContentReportSchema as _, fillUtcSixHours as a, runtimeInfoReportSchema as b, trailingUtcDayWindow as c, utcDayKey as d, utcHourKey as f, pluginPackageContentItemReportSchema as g, pluginOperationalReportSchema as h, fillUtcHours as i, trailingUtcHourWindow as l, pluginOperationalReportFeedSchema as m, HOUR_MS as n, startOfUtcHour as o, healthReportSchema as p, fillUtcDays as r, sumUtcHoursIntoSixHours as s, DAY_MS as t, trailingUtcSixHourWindow as u, pluginSchema as v, skillReportSchema as x, pluginsSchema as y };
229
+ //#region src/chat/conversations/web-message-id.ts
230
+ /**
231
+ * Build the retry-stable Message id shared by web ingress and browser sends.
232
+ * Keep the existing hash and prefix so retries still address stored Messages.
233
+ */
234
+ async function webMessageId(args) {
235
+ const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(`${args.conversationId}\u0000${args.idempotencyKey}`));
236
+ return `api-msg:${Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join("").slice(0, 24)}`;
237
+ }
238
+ //#endregion
239
+ export { skillReportsSchema as C, skillReportSchema as S, pluginPackageContentItemReportSchema as _, fillUtcHours as a, pluginsSchema as b, sumUtcHoursIntoSixHours as c, trailingUtcSixHourWindow as d, utcDayKey as f, pluginOperationalReportSchema as g, pluginOperationalReportFeedSchema as h, fillUtcDays as i, trailingUtcDayWindow as l, healthReportSchema as m, DAY_MS as n, fillUtcSixHours as o, utcHourKey as p, HOUR_MS as r, startOfUtcHour as s, webMessageId as t, trailingUtcHourWindow as u, pluginPackageContentReportSchema as v, runtimeInfoReportSchema as x, pluginSchema as y };
@@ -1,12 +1,11 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-B4FMCO8f.js";
2
- import { B as AgentInvocationLimitError, I as agentBindingSchema, L as agentInvocationSchema, R as createAgentInvocationSchema, n as runAgentWithTimeout, v as PluginCredentialFailureError, wt as AuthorizationFlowDisabledError, z as AgentInvocationBusyError } from "./agent-runner-Cad1RtWn.js";
3
- import { Jt as getSqlExecutor, Kt as getConversationStore, Wt as getConversationEventStore } from "./agent-hooks-CRuRcOg9.js";
4
- import { f as juniorAgentBindings, p as juniorAgentInvocations } from "./executor-B9R4cHte.js";
5
- import { I as openConversationProjection, _ as getTerminalAssistantMessages, o as failTurnRecord, r as saveTurnCheckpoint, s as getTurnRecord } from "./checkpoint-6fkAdB3g.js";
6
- import { pt as appendAndEnqueueInboundMessage } from "./stats-DawHjcTw.js";
7
- import { d as getConversationTurnBoundaryError, l as TurnInputCommitLostError, p as isTurnInputCommitLostError, r as getAssistantReplyText } from "./oauth-authorization-BS4vPJmu.js";
8
- import { t as ConversationTurnLifecycleService } from "./turn-lifecycle-DPDHKi2U.js";
9
- import { n as getPersistedSandboxState, o as persistThreadStateById, r as getPersistedThreadState } from "./thread-state-CAR6gdAm.js";
2
+ import { On as AuthorizationFlowDisabledError, ct as agentInvocationSchema, dt as AgentInvocationLimitError, lt as createAgentInvocationSchema, n as runAgentWithTimeout, st as agentBindingSchema, ut as AgentInvocationBusyError, v as PluginCredentialFailureError, xt as appendAndEnqueueInboundMessage } from "./agent-runner-BGDSjciH.js";
3
+ import { Qt as getConversationStore, Xt as getConversationEventStore, en as getSqlExecutor } from "./agent-hooks-bEwEJhlg.js";
4
+ import { f as juniorAgentBindings, p as juniorAgentInvocations } from "./executor-BXMlFrV6.js";
5
+ import { I as openConversationProjection, _ as getTerminalAssistantMessages, o as failTurnRecord, r as saveTurnCheckpoint, s as getTurnRecord } from "./checkpoint-oZYD3-Ar.js";
6
+ import { d as getConversationTurnBoundaryError, l as TurnInputCommitLostError, p as isTurnInputCommitLostError, r as getAssistantReplyText } from "./oauth-authorization-Cq1GaLIP.js";
7
+ import { t as ConversationTurnLifecycleService } from "./turn-lifecycle-CdiIejXH.js";
8
+ import { n as getPersistedSandboxState, o as persistThreadStateById, r as getPersistedThreadState } from "./thread-state-C_arVuaN.js";
10
9
  import { z } from "zod";
11
10
  import { createHash } from "node:crypto";
12
11
  import { and, asc, count, eq, inArray } from "drizzle-orm";
@@ -1,10 +1,9 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-B4FMCO8f.js";
2
- import { b as isProviderRetryError } from "./client-ihmkx60d.js";
3
- import { C as withLogContext, d as logException, f as logInfo, p as logWarn } from "./logging-CcTvYQ8A.js";
4
- import { a as getChatConfig } from "./config-DMg679BW.js";
5
- import { At as recordConversationRetry, Ct as drainConversationMailbox, Et as getConversationWorkState, Ft as startConversationWork, Ht as isInvalidConversationRecordError, Nt as requestAnotherSlice, St as deadLetterAttempt, Vt as isFinalAttempt, _t as clearConsumedConversationWake, bt as completeConversationWork, dt as ackMessages, gt as checkInConversationWork, jt as releaseConversationWork, kt as recordAttemptFailure, mt as beginConversationResume, wt as ensureConversationWake, xt as countPendingConversationMessages, yt as completeConversationStop, zt as hasConversationStop } from "./stats-DawHjcTw.js";
6
- import { c as ConversationQueueMessageRejectedError } from "./vercel-queue-DIkVcfK4.js";
7
- import { a as getTurnRequestDeadline } from "./job-queue-D2SiTrnt.js";
2
+ import { At as deadLetterAttempt, Dt as completeConversationStop, Lt as recordAttemptFailure, Mt as ensureConversationWake, Ot as completeConversationWork, Pt as getConversationWorkState, Rt as recordConversationRetry, St as beginConversationResume, Tt as clearConsumedConversationWake, Ut as startConversationWork, Vt as requestAnotherSlice, Xt as isInvalidConversationRecordError, Yt as isFinalAttempt, jt as drainConversationMailbox, kt as countPendingConversationMessages, qt as hasConversationStop, wt as checkInConversationWork, yt as ackMessages, zt as releaseConversationWork } from "./agent-runner-BGDSjciH.js";
3
+ import { b as isProviderRetryError } from "./client-Pcxo3lGn.js";
4
+ import { C as withLogContext, d as logException, f as logInfo, p as logWarn } from "./logging-BPBx6WF-.js";
5
+ import { a as getChatConfig } from "./config-CYvEow1F.js";
6
+ import { f as getTurnRequestDeadline, m as ConversationQueueMessageRejectedError } from "./job-queue-AI0_QAgc.js";
8
7
  //#region src/chat/task-execution/worker.ts
9
8
  var worker_exports = /* @__PURE__ */ __exportAll({
10
9
  CONVERSATION_WORK_DEFER_DELAY_MS: () => CONVERSATION_WORK_DEFER_DELAY_MS,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentry/junior",
3
- "version": "0.225.0",
3
+ "version": "0.227.0",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -67,6 +67,7 @@
67
67
  "@opentelemetry/core": "2.9.0",
68
68
  "@sentry/node": "10.65.0",
69
69
  "@sinclair/typebox": "^0.34.49",
70
+ "@slack/types": "^2.21.1",
70
71
  "@slack/web-api": "^7.16.0",
71
72
  "@vercel/blob": "^2.6.1",
72
73
  "@vercel/functions": "^3.6.0",
@@ -85,7 +86,7 @@
85
86
  "pg": "^8.16.3",
86
87
  "yaml": "^2.9.0",
87
88
  "zod": "^4.5.4",
88
- "@sentry/junior-plugin-api": "0.225.0"
89
+ "@sentry/junior-plugin-api": "0.227.0"
89
90
  },
90
91
  "devDependencies": {
91
92
  "@emnapi/core": "^1.10.0",
@@ -104,9 +105,9 @@
104
105
  "typescript": "^6.0.3",
105
106
  "vercel": "^54.4.0",
106
107
  "vitest": "^4.1.7",
107
- "@sentry/junior-github": "0.225.0",
108
+ "@sentry/junior-github": "0.227.0",
108
109
  "@sentry/junior-testing": "0.0.0",
109
- "@sentry/junior-memory": "0.225.0"
110
+ "@sentry/junior-memory": "0.227.0"
110
111
  },
111
112
  "scripts": {
112
113
  "build": "tsdown",
@@ -1,373 +0,0 @@
1
- import { p as logWarn } from "./logging-CcTvYQ8A.js";
2
- import { in as agentTurnTotalTokens, qt as getDb, rn as agentTurnCostUsd } from "./agent-hooks-CRuRcOg9.js";
3
- import { E as juniorConversations, s as juniorAutomationExecutions } from "./executor-B9R4cHte.js";
4
- import { and, asc, count, desc, eq, gte, inArray, lte, max, or, sql } from "drizzle-orm";
5
- //#region src/api/conversations/aggregate.ts
6
- function usageTokenValue(source, field) {
7
- return sql`CASE
8
- WHEN ${source.usage}->>${field} IS NOT NULL
9
- THEN (${source.usage}->>${field})::double precision
10
- ELSE NULL
11
- END`;
12
- }
13
- function tokenValue(source) {
14
- return sql`
15
- CASE
16
- WHEN COALESCE(
17
- ${source.usage}->>'inputTokens',
18
- ${source.usage}->>'outputTokens',
19
- ${source.usage}->>'cachedInputTokens',
20
- ${source.usage}->>'cacheCreationTokens'
21
- ) IS NOT NULL
22
- THEN COALESCE((${source.usage}->>'inputTokens')::double precision, 0)
23
- + COALESCE((${source.usage}->>'outputTokens')::double precision, 0)
24
- + COALESCE((${source.usage}->>'cachedInputTokens')::double precision, 0)
25
- + COALESCE((${source.usage}->>'cacheCreationTokens')::double precision, 0)
26
- WHEN ${source.usage}->>'totalTokens' IS NOT NULL
27
- THEN (${source.usage}->>'totalTokens')::double precision
28
- ELSE NULL
29
- END
30
- `;
31
- }
32
- function costValue(source) {
33
- return conversationUsageCostExpr(source.usage);
34
- }
35
- /** Read one conversation row's usage cost as a SQL expression. */
36
- function conversationUsageCostExpr(usage) {
37
- return sql`
38
- CASE
39
- WHEN ${usage}->'cost'->>'total' IS NOT NULL
40
- THEN (${usage}->'cost'->>'total')::double precision
41
- WHEN COALESCE(
42
- ${usage}->'cost'->>'input',
43
- ${usage}->'cost'->>'output',
44
- ${usage}->'cost'->>'cacheRead',
45
- ${usage}->'cost'->>'cacheWrite'
46
- ) IS NOT NULL
47
- THEN COALESCE((${usage}->'cost'->>'input')::double precision, 0)
48
- + COALESCE((${usage}->'cost'->>'output')::double precision, 0)
49
- + COALESCE((${usage}->'cost'->>'cacheRead')::double precision, 0)
50
- + COALESCE((${usage}->'cost'->>'cacheWrite')::double precision, 0)
51
- ELSE NULL
52
- END
53
- `;
54
- }
55
- /** Select complete conversation metrics inside the database instead of materializing source rows. */
56
- function conversationAggregateColumns(sources) {
57
- const metrics = sources?.metrics ?? juniorConversations;
58
- const roots = sources?.roots ?? juniorConversations;
59
- const conversationCount = sources ? sql`COUNT(DISTINCT ${roots.conversationId})` : sql`COUNT(*)`;
60
- return {
61
- active: sql`${conversationCount} FILTER (
62
- WHERE ${roots.executionStatus} NOT IN ('idle', 'failed')
63
- )::integer`,
64
- conversations: sql`${conversationCount}::integer`,
65
- cachedInputTokens: sql`SUM(${usageTokenValue(metrics, "cachedInputTokens")})::double precision`,
66
- cacheCreationTokens: sql`SUM(${usageTokenValue(metrics, "cacheCreationTokens")})::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/automations/execution-stats.ts
89
- const AUTOMATION_EXECUTION_TYPES = ["scheduled", "event"];
90
- const AUTOMATION_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 automations with no execution history. */
105
- function emptyAutomationRunWindows() {
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 automation execution and its durable conversation when present. */
128
- async function recordAutomationExecution(type, automationId, 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(juniorAutomationExecutions).values({
134
- ...options.conversationId ? { conversationId: options.conversationId } : void 0,
135
- executedAtMs: nowMs,
136
- executionId: options.executionId,
137
- kind: type,
138
- namespace,
139
- status,
140
- automationId
141
- }).onConflictDoNothing({ target: [
142
- juniorAutomationExecutions.kind,
143
- juniorAutomationExecutions.namespace,
144
- juniorAutomationExecutions.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": automationId,
153
- "app.task.execution.type": type
154
- });
155
- }
156
- }
157
- /** Load usage analytics for all automations of one type and namespace. */
158
- async function readAutomationExecutionSummaries(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([juniorAutomationExecutions.automationId], {
166
- conversationId: juniorAutomationExecutions.conversationId,
167
- automationId: juniorAutomationExecutions.automationId
168
- }).from(juniorAutomationExecutions).where(and(eq(juniorAutomationExecutions.kind, type), eq(juniorAutomationExecutions.namespace, namespace))).orderBy(juniorAutomationExecutions.automationId, desc(juniorAutomationExecutions.executedAtMs), desc(juniorAutomationExecutions.executionId)).as("latest_task_execution");
169
- const rows = await db.select({
170
- lastConversationId: latest.conversationId,
171
- lastExecutedAtMs: max(juniorAutomationExecutions.executedAtMs),
172
- runsLast1Day: sql`count(*) filter (where ${juniorAutomationExecutions.executedAtMs} >= ${oneDayAgoMs})::int`,
173
- runsLast7Days: sql`count(*) filter (where ${juniorAutomationExecutions.executedAtMs} >= ${sevenDaysAgoMs})::int`,
174
- runsLast30Days: sql`count(*) filter (where ${juniorAutomationExecutions.executedAtMs} >= ${thirtyDaysAgoMs})::int`,
175
- runsLast90Days: sql`count(*) filter (where ${juniorAutomationExecutions.executedAtMs} >= ${ninetyDaysAgoMs})::int`,
176
- automationId: juniorAutomationExecutions.automationId,
177
- totalRuns: sql`count(*)::int`
178
- }).from(juniorAutomationExecutions).innerJoin(latest, eq(latest.automationId, juniorAutomationExecutions.automationId)).where(and(eq(juniorAutomationExecutions.kind, type), eq(juniorAutomationExecutions.namespace, namespace))).groupBy(juniorAutomationExecutions.automationId, latest.conversationId);
179
- return new Map(rows.map((row) => [row.automationId, {
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 readAutomationExecutionDays(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(${juniorAutomationExecutions.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: juniorAutomationExecutions.kind
203
- }).from(juniorAutomationExecutions).leftJoin(juniorConversations, eq(juniorConversations.conversationId, juniorAutomationExecutions.conversationId)).where(and(gte(juniorAutomationExecutions.executedAtMs, startMs), lte(juniorAutomationExecutions.executedAtMs, endMs), eq(juniorAutomationExecutions.status, "completed"))).groupBy(executionDate, juniorAutomationExecutions.kind).orderBy(asc(executionDate), asc(juniorAutomationExecutions.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 readAutomationExecutionHours(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(${juniorAutomationExecutions.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: juniorAutomationExecutions.kind
232
- }).from(juniorAutomationExecutions).leftJoin(juniorConversations, eq(juniorConversations.conversationId, juniorAutomationExecutions.conversationId)).where(and(gte(juniorAutomationExecutions.executedAtMs, startMs), lte(juniorAutomationExecutions.executedAtMs, endMs), eq(juniorAutomationExecutions.status, "completed"))).groupBy(executionHour, juniorAutomationExecutions.kind).orderBy(asc(executionHour), asc(juniorAutomationExecutions.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 automation execution linked to one conversation, if any. */
248
- async function readAutomationExecutionByConversationId(args) {
249
- const namespace = args.namespace ?? "junior";
250
- const row = (await getDb().select({
251
- kind: juniorAutomationExecutions.kind,
252
- automationId: juniorAutomationExecutions.automationId
253
- }).from(juniorAutomationExecutions).where(and(eq(juniorAutomationExecutions.conversationId, args.conversationId), eq(juniorAutomationExecutions.namespace, namespace), inArray(juniorAutomationExecutions.kind, [...AUTOMATION_EXECUTION_TYPES]))).orderBy(desc(juniorAutomationExecutions.executedAtMs), desc(juniorAutomationExecutions.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
- automationId: row.automationId
259
- };
260
- }
261
- /** Load newest-first executions for one automation, with conversation titles when present. */
262
- async function readAutomationExecutions(args) {
263
- const namespace = args.namespace ?? "junior";
264
- return (await getDb().select({
265
- conversationId: juniorAutomationExecutions.conversationId,
266
- durationMs: juniorConversations.durationMs,
267
- executedAtMs: juniorAutomationExecutions.executedAtMs,
268
- executionId: juniorAutomationExecutions.executionId,
269
- status: juniorAutomationExecutions.status,
270
- title: juniorConversations.title,
271
- usage: juniorConversations.usage
272
- }).from(juniorAutomationExecutions).leftJoin(juniorConversations, eq(juniorConversations.conversationId, juniorAutomationExecutions.conversationId)).where(and(eq(juniorAutomationExecutions.kind, args.kind), eq(juniorAutomationExecutions.namespace, namespace), eq(juniorAutomationExecutions.automationId, args.automationId))).orderBy(desc(juniorAutomationExecutions.executedAtMs), desc(juniorAutomationExecutions.executionId)).limit(args.limit)).map((row) => mapAutomationExecutionRecord(row));
273
- }
274
- /** Load newest-first executions for the supplied viewer-visible tasks. */
275
- async function readAutomationRuns(args) {
276
- const automations = args.automations ?? [];
277
- const conversationIds = [...new Set((args.conversationIds ?? []).filter((conversationId) => conversationId.trim().length > 0))];
278
- if (automations.length === 0 && conversationIds.length === 0) return [];
279
- const namespace = args.namespace ?? "junior";
280
- const selectors = [...automations.map((task) => and(eq(juniorAutomationExecutions.kind, task.kind), eq(juniorAutomationExecutions.automationId, task.automationId))), ...conversationIds.length > 0 ? [inArray(juniorAutomationExecutions.conversationId, conversationIds)] : []];
281
- return (await getDb().select({
282
- conversationId: juniorAutomationExecutions.conversationId,
283
- durationMs: juniorConversations.durationMs,
284
- executedAtMs: juniorAutomationExecutions.executedAtMs,
285
- executionId: juniorAutomationExecutions.executionId,
286
- kind: juniorAutomationExecutions.kind,
287
- status: juniorAutomationExecutions.status,
288
- automationId: juniorAutomationExecutions.automationId,
289
- title: juniorConversations.title,
290
- usage: juniorConversations.usage
291
- }).from(juniorAutomationExecutions).leftJoin(juniorConversations, eq(juniorConversations.conversationId, juniorAutomationExecutions.conversationId)).where(and(eq(juniorAutomationExecutions.namespace, namespace), or(...selectors))).orderBy(desc(juniorAutomationExecutions.executedAtMs), desc(juniorAutomationExecutions.executionId)).limit(args.limit)).flatMap((row) => {
292
- if (row.kind !== "scheduled" && row.kind !== "event") return [];
293
- return [{
294
- ...mapAutomationExecutionRecord(row),
295
- kind: row.kind,
296
- automationId: row.automationId
297
- }];
298
- });
299
- }
300
- function mapAutomationExecutionRecord(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 automation by status. */
317
- async function readAutomationExecutionStatusDays(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(${juniorAutomationExecutions.executedAtMs} / 1000.0) at time zone 'UTC', 'YYYY-MM-DD')`;
324
- const rows = await getDb().select({
325
- count: count(),
326
- date: executionDate,
327
- status: juniorAutomationExecutions.status
328
- }).from(juniorAutomationExecutions).where(and(eq(juniorAutomationExecutions.kind, args.kind), eq(juniorAutomationExecutions.namespace, namespace), eq(juniorAutomationExecutions.automationId, args.automationId), gte(juniorAutomationExecutions.executedAtMs, startMs), lte(juniorAutomationExecutions.executedAtMs, endMs), inArray(juniorAutomationExecutions.status, [...AUTOMATION_EXECUTION_STATUSES]))).groupBy(executionDate, juniorAutomationExecutions.status).orderBy(asc(executionDate), asc(juniorAutomationExecutions.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 automation by hour. */
344
- async function readAutomationExecutionStatusHours(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(${juniorAutomationExecutions.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: juniorAutomationExecutions.status
357
- }).from(juniorAutomationExecutions).where(and(eq(juniorAutomationExecutions.kind, args.kind), eq(juniorAutomationExecutions.namespace, namespace), eq(juniorAutomationExecutions.automationId, args.automationId), gte(juniorAutomationExecutions.executedAtMs, startMs), lte(juniorAutomationExecutions.executedAtMs, endMs), inArray(juniorAutomationExecutions.status, [...AUTOMATION_EXECUTION_STATUSES]))).groupBy(executionHour, juniorAutomationExecutions.status).orderBy(asc(executionHour), asc(juniorAutomationExecutions.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 { readAutomationExecutionStatusDays as a, readAutomationExecutions as c, conversationActiveDaysColumn as d, conversationAggregateColumns as f, readAutomationExecutionHours as i, readAutomationRuns as l, readAutomationExecutionByConversationId as n, readAutomationExecutionStatusHours as o, conversationRangeColumns as p, readAutomationExecutionDays as r, readAutomationExecutionSummaries as s, emptyAutomationRunWindows as t, recordAutomationExecution as u };
@@ -1,65 +0,0 @@
1
- import { z } from "zod";
2
- import "@sentry/junior-plugin-api";
3
- //#region src/chat/conversations/cards.d.ts
4
- /** Built-in response types accepted by Message storage and delivery. */
5
- declare const messageCardSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
6
- kind: z.ZodLiteral<"automation">;
7
- id: z.ZodString;
8
- title: z.ZodString;
9
- url: z.ZodNullable<z.ZodString>;
10
- instruction: z.ZodString;
11
- trigger: z.ZodString;
12
- warning: z.ZodNullable<z.ZodString>;
13
- }, z.core.$strict>, z.ZodObject<{
14
- kind: z.ZodLiteral<"object">;
15
- key: z.ZodString;
16
- label: z.ZodString;
17
- objectType: z.ZodEnum<{
18
- task: "task";
19
- code_change: "code_change";
20
- automation: "automation";
21
- item: "item";
22
- }>;
23
- title: z.ZodString;
24
- url: z.ZodNullable<z.ZodURL>;
25
- description: z.ZodOptional<z.ZodString>;
26
- status: z.ZodOptional<z.ZodString>;
27
- trigger: z.ZodOptional<z.ZodString>;
28
- warning: z.ZodOptional<z.ZodString>;
29
- plugin: z.ZodString;
30
- }, z.core.$strict>], "kind">;
31
- type MessageCard = z.output<typeof messageCardSchema>;
32
- /** Render each built-in card with its own text format. */
33
- declare function messageCardText(card: MessageCard): string;
34
- //#endregion
35
- //#region src/chat/conversations/history.d.ts
36
- /** Where a failed turn stopped. */
37
- declare const conversationTurnFailureCodeSchema: z.ZodEnum<{
38
- agent_run_failed: "agent_run_failed";
39
- delivery_failed: "delivery_failed";
40
- model_execution_failed: "model_execution_failed";
41
- persistence_failed: "persistence_failed";
42
- }>;
43
- /**
44
- * Why a failed turn stopped.
45
- * Values are fixed labels only. Do not store raw exception text.
46
- */
47
- declare const conversationTurnFailureReasonSchema: z.ZodEnum<{
48
- unknown: "unknown";
49
- capacity: "capacity";
50
- auth: "auth";
51
- permission: "permission";
52
- rate_limit: "rate_limit";
53
- timeout: "timeout";
54
- network: "network";
55
- server: "server";
56
- invalid_request: "invalid_request";
57
- invalid_response: "invalid_response";
58
- quota: "quota";
59
- content_policy: "content_policy";
60
- empty_output: "empty_output";
61
- tool_errors: "tool_errors";
62
- suppressed_output: "suppressed_output";
63
- }>;
64
- //#endregion
65
- export { messageCardText as i, conversationTurnFailureReasonSchema as n, MessageCard as r, conversationTurnFailureCodeSchema as t };
@@ -1,63 +0,0 @@
1
- import { a as getChatConfig } from "./config-DMg679BW.js";
2
- import { a as signQueueMessage, i as QUEUE_SIGNATURE_MAX_AGE_MS, o as verifyQueueMessage, s as createVercelQueueClient } from "./vercel-queue-DIkVcfK4.js";
3
- import { AsyncLocalStorage } from "node:async_hooks";
4
- import { z } from "zod";
5
- import { createHash } from "node:crypto";
6
- //#region src/chat/runtime/request-deadline.ts
7
- const requestDeadlineStorage = new AsyncLocalStorage();
8
- function createTurnRequestDeadline(startedAtMs) {
9
- return {
10
- startedAtMs,
11
- deadlineAtMs: startedAtMs + Math.max(1, getChatConfig().functionMaxDurationSeconds * 1e3 - 2e4)
12
- };
13
- }
14
- /** Return the host request deadline inherited by the current async turn. */
15
- function getTurnRequestDeadline() {
16
- return requestDeadlineStorage.getStore();
17
- }
18
- /** Run work with one host request deadline shared by nested queued turns. */
19
- function runWithTurnRequestDeadline(callback, startedAtMs = Date.now()) {
20
- if (requestDeadlineStorage.getStore()) return callback();
21
- return requestDeadlineStorage.run(createTurnRequestDeadline(startedAtMs), callback);
22
- }
23
- //#endregion
24
- //#region src/chat/sandbox/snapshot/job-queue.ts
25
- /** Send Workspace snapshot build messages. */
26
- const SIGNATURE_CONTEXT = "junior.workspace_snapshot_queue.v1";
27
- const SIGNATURE_VERSION = "v1";
28
- const WORKSPACE_SNAPSHOT_JOB_QUEUE_TOPIC = "junior_workspace_snapshots";
29
- const workspaceSnapshotJobSign = {
30
- context: SIGNATURE_CONTEXT,
31
- schema: z.object({
32
- workspaceId: z.string().uuid(),
33
- profileHash: z.string().min(1)
34
- }).strict(),
35
- signatureVersion: SIGNATURE_VERSION,
36
- parts: (message) => [message.workspaceId, message.profileHash]
37
- };
38
- function jobId(message) {
39
- return `workspace-snapshot_${createHash("sha256").update(message.workspaceId).update("\0").update(message.profileHash).digest("hex").slice(0, 32)}`;
40
- }
41
- /** Sign a Workspace snapshot job for tests and local checks. */
42
- function signWorkspaceSnapshotJobMessage(message, nowMs = Date.now()) {
43
- return signQueueMessage(workspaceSnapshotJobSign, message, nowMs);
44
- }
45
- /** Check that a recent queue message came from Junior. */
46
- function verifyWorkspaceSnapshotJobMessage(value, nowMs = Date.now()) {
47
- return verifyQueueMessage(workspaceSnapshotJobSign, value, nowMs);
48
- }
49
- async function send(message, idempotencyKey) {
50
- const options = { retentionSeconds: QUEUE_SIGNATURE_MAX_AGE_MS / 1e3 };
51
- if (idempotencyKey) options.idempotencyKey = idempotencyKey;
52
- await createVercelQueueClient().send(WORKSPACE_SNAPSHOT_JOB_QUEUE_TOPIC, signWorkspaceSnapshotJobMessage(message), options);
53
- }
54
- /** Send a job unless the same Workspace build already has one. */
55
- async function sendWorkspaceSnapshotJob(message) {
56
- await send(message, jobId(message));
57
- }
58
- /** Send the next job for a Workspace build that is still running. */
59
- async function sendNextWorkspaceSnapshotJob(message) {
60
- await send(message);
61
- }
62
- //#endregion
63
- export { getTurnRequestDeadline as a, verifyWorkspaceSnapshotJobMessage as i, sendNextWorkspaceSnapshotJob as n, runWithTurnRequestDeadline as o, sendWorkspaceSnapshotJob as r, WORKSPACE_SNAPSHOT_JOB_QUEUE_TOPIC as t };