@sentry/junior 0.221.0 → 0.222.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 (64) hide show
  1. package/dist/{agent-CFrfUdN5.js → agent-7kKtDe-6.js} +47 -27
  2. package/dist/{agent-hooks-kjLDY-Aa.js → agent-hooks-DkriF84n.js} +9 -8
  3. package/dist/{agent-runner-DMMa36Zl.js → agent-runner-D0ImXS7U.js} +6 -5
  4. package/dist/api/schema.d.ts +51 -2
  5. package/dist/api/schema.js +4 -4
  6. package/dist/api.js +18 -515
  7. package/dist/{app-BYD2Nyji.d.ts → app-C0zbsnr7.d.ts} +1 -1
  8. package/dist/app.d.ts +1 -1
  9. package/dist/app.js +153 -32
  10. package/dist/{auth-pause-state-TdhAyYM4.js → auth-pause-state-3OT67TA8.js} +52 -7
  11. package/dist/{briefs-CIN2DMSo.js → briefs-CNH1ztn5.js} +4 -4
  12. package/dist/{catalog-runtime-D1v0KsgY.js → catalog-runtime-XH_LFA_7.js} +1 -1
  13. package/dist/{checkpoint-B2-uc-1h.js → checkpoint-CRod8es5.js} +8 -7
  14. package/dist/cli/chat.js +13 -13
  15. package/dist/cli/check.js +3 -3
  16. package/dist/cli/main.js +1 -1
  17. package/dist/cli/plugins.js +3 -3
  18. package/dist/cli/snapshot-create.js +3 -3
  19. package/dist/cli/upgrade.js +3 -3
  20. package/dist/{client-DIe9JhwF.js → client-CcSboWx_.js} +2 -2
  21. package/dist/{config-0_JixokJ.js → config-CGYv-YPE.js} +2 -2
  22. package/dist/{conversation-BSRGzJmY.js → conversation-BBDt88di.js} +46 -3
  23. package/dist/{conversation-privacy-6NLCEkzx.js → conversation-privacy-BGjdDVWD.js} +1 -1
  24. package/dist/{credential-sync-Dqg2o90r.js → credential-sync-BfzGNruT.js} +125 -30
  25. package/dist/{execution-stats-vnXVMVeu.js → execution-stats-D97ePWuM.js} +3 -3
  26. package/dist/{executor-CmZKtNpH.js → executor-BLBZ-UB8.js} +1 -1
  27. package/dist/{history-ClE4toxe.d.ts → history-CaV8Ww7M.d.ts} +16 -1
  28. package/dist/instrumentation.js +2 -2
  29. package/dist/{job-queue-B1k3woMW.js → job-queue-_8gxwDzt.js} +1 -1
  30. package/dist/{logging-D2YJv_PA.js → logging-qmsMdU0y.js} +1 -1
  31. package/dist/nitro.d.ts +1 -1
  32. package/dist/nitro.js +3 -3
  33. package/dist/{oauth-callback-server-BQtO5l5M.js → oauth-callback-server-Mjfm46A5.js} +2 -2
  34. package/dist/{pending-auth-DuSNoTpn.js → pending-auth-_1Ry-_Bw.js} +2 -2
  35. package/dist/{profile-C3TEFAVI.js → profile-DbG8AlNd.js} +4 -4
  36. package/dist/{prompt-BkaHwBW0.js → prompt-B8rCQI7K.js} +1 -1
  37. package/dist/{registry-Bp0kd2xe.js → registry-DGyQCsiy.js} +1 -1
  38. package/dist/reporting-window-DbUqng0P.js +229 -0
  39. package/dist/{resolve-BABNNBLL.js → resolve-D5SqDbCA.js} +2 -2
  40. package/dist/{runner-Bvn90ijl.js → runner-BRAFjJhe.js} +21 -10
  41. package/dist/{sandbox-egress-signals-DLfYAOiO.js → sandbox-egress-signals-CdI1aVHT.js} +1 -1
  42. package/dist/{schema-YPJXVcOW.js → schema-CTOODa3L.js} +5 -128
  43. package/dist/{short-title-C2fM-ERl.js → short-title-CB2fxEyx.js} +2 -2
  44. package/dist/{skills-D1otDVYp.js → skills-BoS3b8cg.js} +2 -2
  45. package/dist/{spawn-C-fAS-Rk.js → spawn-BXCU1udr.js} +2 -2
  46. package/dist/{stats-BfUFTUrM.js → stats-qUXQZq-w.js} +52 -13
  47. package/dist/{task-queue-VdYCCwO0.js → task-queue-Di_q8922.js} +3 -3
  48. package/dist/{task-runner-6tzKHNbM.js → task-runner-4rCppQMo.js} +8 -8
  49. package/dist/{thread-state-CD_fsyrM.js → thread-state-2Paza8DV.js} +5 -5
  50. package/dist/{turn-execution-eVhqozjK.js → turn-execution--F7a9kEU.js} +3 -3
  51. package/dist/{turn-lifecycle-CxAtVANu.js → turn-lifecycle-f-y0Irpi.js} +1 -1
  52. package/dist/{validation-CMERqrCD.js → validation-Be9lSORU.js} +1 -1
  53. package/dist/{version-C8XFxpkQ.js → version-BydrOZMQ.js} +1 -1
  54. package/dist/version.js +1 -1
  55. package/dist/{web-authorization-Dq2NDhY0.js → web-authorization-BdfOkTuG.js} +1 -1
  56. package/dist/web-input-DegYUyKU.js +899 -0
  57. package/dist/{work-DCwaUeWu.js → work-Citqpnfc.js} +9 -9
  58. package/dist/{worker-grswNVoc.js → worker-Bn_HFyvM.js} +5 -5
  59. package/migrations/0044_event_automation_channel_destinations.sql +36 -0
  60. package/migrations/meta/0044_snapshot.json +3473 -0
  61. package/migrations/meta/_journal.json +7 -0
  62. package/package.json +5 -5
  63. package/dist/reporting-schema-DosTN__Q.js +0 -105
  64. package/dist/web-input-Bdh_rCZ7.js +0 -392
@@ -0,0 +1,229 @@
1
+ import { z } from "zod";
2
+ //#region src/reporting-schema.ts
3
+ const healthReportSchema = z.object({
4
+ status: z.literal("ok"),
5
+ service: z.string(),
6
+ timestamp: z.string()
7
+ }).strict();
8
+ const pluginSchema = z.object({
9
+ configKeys: z.array(z.string()),
10
+ description: z.string(),
11
+ displayName: z.string(),
12
+ name: z.string()
13
+ }).strict();
14
+ const pluginsSchema = z.array(pluginSchema);
15
+ const skillReportSchema = z.object({
16
+ name: z.string(),
17
+ pluginProvider: z.string().optional()
18
+ }).strict();
19
+ const skillReportsSchema = z.array(skillReportSchema);
20
+ const pluginPackageContentItemReportSchema = z.object({
21
+ dir: z.string(),
22
+ hasMigrationsDir: z.boolean(),
23
+ hasSkillsDir: z.boolean(),
24
+ packageName: z.string()
25
+ }).strict();
26
+ const pluginPackageContentReportSchema = z.object({
27
+ packageNames: z.array(z.string()),
28
+ packages: z.array(pluginPackageContentItemReportSchema),
29
+ manifestRoots: z.array(z.string()),
30
+ skillRoots: z.array(z.string()),
31
+ tracingIncludes: z.array(z.string())
32
+ }).strict();
33
+ const runtimeInfoReportSchema = z.object({
34
+ cwd: z.string(),
35
+ homeDir: z.string(),
36
+ descriptionText: z.string().optional(),
37
+ providers: z.array(z.string()),
38
+ skills: z.array(skillReportSchema),
39
+ packagedContent: pluginPackageContentReportSchema
40
+ }).strict();
41
+ const pluginOperationalToneSchema = z.enum([
42
+ "danger",
43
+ "good",
44
+ "neutral",
45
+ "warning"
46
+ ]);
47
+ const pluginOperationalMetricSchema = z.object({
48
+ label: z.string(),
49
+ tone: pluginOperationalToneSchema.optional(),
50
+ value: z.string()
51
+ }).strict();
52
+ const pluginOperationalFieldSchema = z.object({
53
+ key: z.string(),
54
+ label: z.string()
55
+ }).strict();
56
+ const pluginOperationalRecordSchema = z.object({
57
+ id: z.string(),
58
+ tone: pluginOperationalToneSchema.optional(),
59
+ values: z.record(z.string(), z.string())
60
+ }).strict();
61
+ const pluginOperationalRecordSetSchema = z.object({
62
+ fields: z.array(pluginOperationalFieldSchema).optional(),
63
+ emptyText: z.string().optional(),
64
+ records: z.array(pluginOperationalRecordSchema).optional(),
65
+ title: z.string()
66
+ }).strict();
67
+ const pluginOperationalBarChartWidgetSchema = z.object({
68
+ categories: z.array(z.object({
69
+ id: z.string().min(1),
70
+ label: z.string().min(1),
71
+ values: z.record(z.string(), z.number().finite())
72
+ }).strict()).max(100),
73
+ description: z.string().optional(),
74
+ emptyText: z.string().optional(),
75
+ id: z.string().min(1),
76
+ series: z.array(z.object({
77
+ format: z.literal("usd").optional(),
78
+ key: z.string().min(1),
79
+ label: z.string().min(1),
80
+ tone: pluginOperationalToneSchema.optional()
81
+ }).strict()).min(1).max(8),
82
+ timeRangeDays: z.array(z.union([
83
+ z.literal(1),
84
+ z.literal(7),
85
+ z.literal(30),
86
+ z.literal(90)
87
+ ])).min(1).max(4).optional(),
88
+ title: z.string().min(1),
89
+ type: z.literal("bar_chart")
90
+ }).strict();
91
+ const pluginOperationalReportSchema = z.object({
92
+ generatedAt: z.string().optional(),
93
+ metrics: z.array(pluginOperationalMetricSchema).optional(),
94
+ recordSets: z.array(pluginOperationalRecordSetSchema).optional(),
95
+ title: z.string().optional(),
96
+ pluginName: z.string(),
97
+ widgets: z.array(pluginOperationalBarChartWidgetSchema).max(12).optional()
98
+ }).strict();
99
+ const pluginOperationalReportFeedSchema = z.object({
100
+ generatedAt: z.string(),
101
+ reports: z.array(pluginOperationalReportSchema),
102
+ source: z.literal("plugins")
103
+ }).strict();
104
+ //#endregion
105
+ //#region src/api/reporting-window.ts
106
+ /** Shared UTC day/hour/six-hour windows for dashboard activity series. */
107
+ const HOUR_MS = 36e5;
108
+ const SIX_HOUR_MS = 6 * HOUR_MS;
109
+ const DAY_MS = 24 * HOUR_MS;
110
+ /** Start of the UTC calendar day containing `valueMs`. */
111
+ function startOfUtcDay(valueMs) {
112
+ const date = new Date(valueMs);
113
+ date.setUTCHours(0, 0, 0, 0);
114
+ return date;
115
+ }
116
+ /** Start of the UTC hour containing `valueMs`. */
117
+ function startOfUtcHour(valueMs) {
118
+ const date = new Date(valueMs);
119
+ date.setUTCMinutes(0, 0, 0);
120
+ return date;
121
+ }
122
+ /** Start of the UTC 6-hour bucket containing `valueMs` (00/06/12/18). */
123
+ function startOfUtcSixHour(valueMs) {
124
+ const date = startOfUtcHour(valueMs);
125
+ date.setUTCHours(Math.floor(date.getUTCHours() / 6) * 6, 0, 0, 0);
126
+ return date;
127
+ }
128
+ /** UTC day key `YYYY-MM-DD`. */
129
+ function utcDayKey(value) {
130
+ return (typeof value === "number" ? new Date(value) : value).toISOString().slice(0, 10);
131
+ }
132
+ /** UTC hour key `YYYY-MM-DDTHH`. */
133
+ function utcHourKey(value) {
134
+ return (typeof value === "number" ? new Date(value) : value).toISOString().slice(0, 13);
135
+ }
136
+ /** UTC 6-hour bucket key `YYYY-MM-DDTHH` at 00/06/12/18. */
137
+ function utcSixHourKey(value) {
138
+ return utcHourKey(startOfUtcSixHour(typeof value === "number" ? value : value.getTime()));
139
+ }
140
+ /** Inclusive trailing UTC day window ending on today's UTC day. */
141
+ function trailingUtcDayWindow(nowMs, dayCount) {
142
+ const end = startOfUtcDay(nowMs);
143
+ const start = new Date(end);
144
+ start.setUTCDate(start.getUTCDate() - (dayCount - 1));
145
+ return {
146
+ end,
147
+ start
148
+ };
149
+ }
150
+ /** Inclusive trailing UTC hour window ending on the current UTC hour. */
151
+ function trailingUtcHourWindow(nowMs, hourCount = 24) {
152
+ const end = startOfUtcHour(nowMs);
153
+ return {
154
+ end,
155
+ start: /* @__PURE__ */ new Date(end.getTime() - (hourCount - 1) * HOUR_MS)
156
+ };
157
+ }
158
+ /** Inclusive trailing UTC 6-hour window ending on the current 6h bucket. */
159
+ function trailingUtcSixHourWindow(nowMs, bucketCount = 28) {
160
+ const end = startOfUtcSixHour(nowMs);
161
+ return {
162
+ end,
163
+ start: /* @__PURE__ */ new Date(end.getTime() - (bucketCount - 1) * SIX_HOUR_MS)
164
+ };
165
+ }
166
+ /** Fill a fixed UTC day window from a sparse map. */
167
+ function fillUtcDays(args) {
168
+ const { end, start } = trailingUtcDayWindow(args.nowMs, args.count);
169
+ const items = [];
170
+ for (const cursor = new Date(start); cursor.getTime() <= end.getTime(); cursor.setUTCDate(cursor.getUTCDate() + 1)) {
171
+ const date = utcDayKey(cursor);
172
+ items.push(args.rows.get(date) ?? args.empty(date));
173
+ }
174
+ return items;
175
+ }
176
+ /** Fill a fixed UTC hour window from a sparse map. */
177
+ function fillUtcHours(args) {
178
+ const hourCount = args.count ?? 24;
179
+ const { end, start } = trailingUtcHourWindow(args.nowMs, hourCount);
180
+ const items = [];
181
+ for (const cursor = new Date(start); cursor.getTime() <= end.getTime(); cursor.setTime(cursor.getTime() + HOUR_MS)) {
182
+ const date = utcHourKey(cursor);
183
+ items.push(args.rows.get(date) ?? args.empty(date));
184
+ }
185
+ return items;
186
+ }
187
+ /** Fill a fixed UTC 6-hour window from a map of known rows. */
188
+ function fillUtcSixHours(args) {
189
+ const bucketCount = args.count ?? 28;
190
+ const { end, start } = trailingUtcSixHourWindow(args.nowMs, bucketCount);
191
+ const items = [];
192
+ for (const cursor = new Date(start); cursor.getTime() <= end.getTime(); cursor.setTime(cursor.getTime() + SIX_HOUR_MS)) {
193
+ const date = utcSixHourKey(cursor);
194
+ items.push(args.rows.get(date) ?? args.empty(date));
195
+ }
196
+ return items;
197
+ }
198
+ /**
199
+ * Sum hour rows into trailing 6-hour buckets.
200
+ * Adds number fields. Keeps other fields from the first row in the bucket.
201
+ * Sets `date` to the 6-hour bucket key.
202
+ */
203
+ function sumUtcHoursIntoSixHours(args) {
204
+ const bucketCount = args.count ?? 28;
205
+ const bySix = /* @__PURE__ */ new Map();
206
+ for (const hour of args.hours) {
207
+ const key = utcSixHourKey(Date.parse(`${hour.date}:00:00.000Z`));
208
+ const next = {
209
+ ...bySix.get(key) ?? args.empty(key),
210
+ date: key
211
+ };
212
+ for (const [field, value] of Object.entries(hour)) {
213
+ if (field === "date") continue;
214
+ if (typeof value === "number") {
215
+ const prior = next[field];
216
+ next[field] = (typeof prior === "number" ? prior : 0) + value;
217
+ }
218
+ }
219
+ bySix.set(key, next);
220
+ }
221
+ return fillUtcSixHours({
222
+ count: bucketCount,
223
+ empty: args.empty,
224
+ nowMs: args.nowMs,
225
+ rows: bySix
226
+ });
227
+ }
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 };
@@ -1,5 +1,5 @@
1
- import { C as withSpan, _ as setSpanAttributes } from "./logging-D2YJv_PA.js";
2
- import { A as sleep, P as SANDBOX_WORKSPACE_ROOT, r as isStale, t as create, u as isSandboxUnavailableError, v as getVercelSandboxCredentials, w as getStateAdapter, x as runNonInteractiveCommand } from "./profile-C3TEFAVI.js";
1
+ import { C as withSpan, _ as setSpanAttributes } from "./logging-qmsMdU0y.js";
2
+ import { A as sleep, P as SANDBOX_WORKSPACE_ROOT, r as isStale, t as create, u as isSandboxUnavailableError, v as getVercelSandboxCredentials, w as getStateAdapter, x as runNonInteractiveCommand } from "./profile-DbG8AlNd.js";
3
3
  import { z } from "zod";
4
4
  import { FileSystem, Sandbox } from "@vercel/sandbox";
5
5
  //#region src/chat/sandbox/resources.ts
@@ -1,16 +1,25 @@
1
- import { p as authorizationId } from "./agent-CFrfUdN5.js";
2
- import { S as withLogContext, u as logException, y as setTags } from "./logging-D2YJv_PA.js";
1
+ import { p as authorizationId } from "./agent-7kKtDe-6.js";
2
+ import { S as withLogContext, u as logException, y as setTags } from "./logging-qmsMdU0y.js";
3
3
  import { t as credentialContextForActor } from "./context-Bplcgypl.js";
4
- import { Ht as getConversationEventStore, Wt as getConversationStore } from "./agent-hooks-kjLDY-Aa.js";
5
- import { F as loadProjection, V as recordAuthorizationCompleted, X as persistConversationMessages, Y as hydrateConversationMessages, ct as recordDeliveredAssistantMessage, d as persistWithRetry, j as commitAcceptedReply, ot as markConversationMessage, r as saveTurnCheckpoint, st as normalizeConversationText, tt as buildConversationContext, ut as upsertConversationMessage } from "./checkpoint-B2-uc-1h.js";
6
- import { S as startActiveTurn, s as getAssistantReplyText, x as markTurnFailed } from "./pending-auth-DuSNoTpn.js";
7
- import { n as scheduleSessionCompletedPluginTasks, t as processPluginTask } from "./task-runner-6tzKHNbM.js";
8
- import { t as ConversationTurnLifecycleService } from "./turn-lifecycle-CxAtVANu.js";
9
- import { n as getPersistedSandboxState, o as persistThreadStateById, r as getPersistedThreadState, s as coerceThreadConversationState } from "./thread-state-CD_fsyrM.js";
10
- import { d as buildDeliveredTurnStatePatch, r as finalizeFailedTurnReplyWithEvent, t as completeAuthPauseTurn } from "./auth-pause-state-TdhAyYM4.js";
4
+ import { Ht as getConversationEventStore, Wt as getConversationStore } from "./agent-hooks-DkriF84n.js";
5
+ import { k as messageCardText } from "./conversation-BBDt88di.js";
6
+ import { F as loadProjection, V as recordAuthorizationCompleted, X as persistConversationMessages, Y as hydrateConversationMessages, ct as recordDeliveredAssistantMessage, d as persistWithRetry, j as commitAcceptedReply, ot as markConversationMessage, r as saveTurnCheckpoint, st as normalizeConversationText, tt as buildConversationContext, ut as upsertConversationMessage } from "./checkpoint-CRod8es5.js";
7
+ import { S as startActiveTurn, s as getAssistantReplyText, x as markTurnFailed } from "./pending-auth-_1Ry-_Bw.js";
8
+ import { n as scheduleSessionCompletedPluginTasks, t as processPluginTask } from "./task-runner-4rCppQMo.js";
9
+ import { t as ConversationTurnLifecycleService } from "./turn-lifecycle-f-y0Irpi.js";
10
+ import { n as getPersistedSandboxState, o as persistThreadStateById, r as getPersistedThreadState, s as coerceThreadConversationState } from "./thread-state-2Paza8DV.js";
11
+ import { f as buildDeliveredTurnStatePatch, r as finalizeFailedTurnReplyWithEvent, s as loadPendingMessageCards, t as completeAuthPauseTurn } from "./auth-pause-state-3OT67TA8.js";
11
12
  import { randomUUID } from "node:crypto";
12
13
  import { createLocalSource, localDestinationSchema } from "@sentry/junior-plugin-api";
13
14
  //#region src/chat/local/runner.ts
15
+ /**
16
+ * Local agent turn runtime.
17
+ *
18
+ * This module owns the Slack-free execution boundary for CLI-originated turns:
19
+ * it persists local conversation state, invokes the shared agent runner with
20
+ * a local destination, and only commits assistant delivery after the CLI sink
21
+ * accepts each completed tool-free assistant message.
22
+ */
14
23
  const SENTRY_EVENT_ID_PATTERN = /^[a-f0-9]{32}$/i;
15
24
  const LOCAL_FAILURE_EVENT_NAMES = {
16
25
  agent_run_failed: "local.agent_run.failed",
@@ -132,9 +141,11 @@ async function runLocalAgentTurnInContext(input, deps) {
132
141
  const text = typeof reply === "string" ? reply : getAssistantReplyText(reply);
133
142
  if (!text?.trim()) return;
134
143
  failureCode = "delivery_failed";
135
- await deps.deliverReply({ text });
144
+ const cards = await loadPendingMessageCards(input.conversationId);
145
+ await deps.deliverReply({ text: [text, ...cards.map(messageCardText)].join("\n\n") });
136
146
  assistantMessageDelivered = true;
137
147
  const recordedMessageId = recordDeliveredAssistantMessage({
148
+ cards,
138
149
  conversation,
139
150
  sessionId: turnId,
140
151
  text,
@@ -1,4 +1,4 @@
1
- import { Y as sandboxEgressSignalsResponseSchema } from "./agent-CFrfUdN5.js";
1
+ import { Y as sandboxEgressSignalsResponseSchema } from "./agent-7kKtDe-6.js";
2
2
  //#region src/chat/local/sandbox-egress-signals.ts
3
3
  const SANDBOX_EGRESS_SIGNALS_PATH = "/api/internal/sandbox-egress/signals";
4
4
  const LOCAL_DEV_SERVER_TIMEOUT_MS = 1e3;
@@ -1,136 +1,12 @@
1
1
  import { t as juniorDestinationKindSchema } from "./destinations-BeBiJeEM.js";
2
- import { E as conversationSummaryReportSchema, n as actorIdentitySchema, w as conversationStatsItemSchema } from "./conversation-BSRGzJmY.js";
3
- import "./reporting-schema-DosTN__Q.js";
2
+ import { E as conversationSummaryReportSchema, n as actorIdentitySchema, w as conversationStatsItemSchema } from "./conversation-BBDt88di.js";
3
+ import { i as fillUtcHours, r as fillUtcDays, s as sumUtcHoursIntoSixHours } from "./reporting-window-DbUqng0P.js";
4
4
  import { z } from "zod";
5
5
  import { codeChangeStateSchema, taskOutcomeSchema } from "@sentry/junior-plugin-api";
6
6
  //#region src/api/schema/common.ts
7
7
  /** Stable error body returned by Junior-owned REST endpoints. */
8
8
  const apiErrorSchema = z.object({ error: z.string().min(1) }).strict();
9
9
  //#endregion
10
- //#region src/api/reporting-window.ts
11
- /** Shared UTC day/hour/six-hour windows for dashboard activity series. */
12
- const HOUR_MS = 36e5;
13
- const SIX_HOUR_MS = 6 * HOUR_MS;
14
- const DAY_MS = 24 * HOUR_MS;
15
- /** Start of the UTC calendar day containing `valueMs`. */
16
- function startOfUtcDay(valueMs) {
17
- const date = new Date(valueMs);
18
- date.setUTCHours(0, 0, 0, 0);
19
- return date;
20
- }
21
- /** Start of the UTC hour containing `valueMs`. */
22
- function startOfUtcHour(valueMs) {
23
- const date = new Date(valueMs);
24
- date.setUTCMinutes(0, 0, 0);
25
- return date;
26
- }
27
- /** Start of the UTC 6-hour bucket containing `valueMs` (00/06/12/18). */
28
- function startOfUtcSixHour(valueMs) {
29
- const date = startOfUtcHour(valueMs);
30
- date.setUTCHours(Math.floor(date.getUTCHours() / 6) * 6, 0, 0, 0);
31
- return date;
32
- }
33
- /** UTC day key `YYYY-MM-DD`. */
34
- function utcDayKey(value) {
35
- return (typeof value === "number" ? new Date(value) : value).toISOString().slice(0, 10);
36
- }
37
- /** UTC hour key `YYYY-MM-DDTHH`. */
38
- function utcHourKey(value) {
39
- return (typeof value === "number" ? new Date(value) : value).toISOString().slice(0, 13);
40
- }
41
- /** UTC 6-hour bucket key `YYYY-MM-DDTHH` at 00/06/12/18. */
42
- function utcSixHourKey(value) {
43
- return utcHourKey(startOfUtcSixHour(typeof value === "number" ? value : value.getTime()));
44
- }
45
- /** Inclusive trailing UTC day window ending on today's UTC day. */
46
- function trailingUtcDayWindow(nowMs, dayCount) {
47
- const end = startOfUtcDay(nowMs);
48
- const start = new Date(end);
49
- start.setUTCDate(start.getUTCDate() - (dayCount - 1));
50
- return {
51
- end,
52
- start
53
- };
54
- }
55
- /** Inclusive trailing UTC hour window ending on the current UTC hour. */
56
- function trailingUtcHourWindow(nowMs, hourCount = 24) {
57
- const end = startOfUtcHour(nowMs);
58
- return {
59
- end,
60
- start: /* @__PURE__ */ new Date(end.getTime() - (hourCount - 1) * HOUR_MS)
61
- };
62
- }
63
- /** Inclusive trailing UTC 6-hour window ending on the current 6h bucket. */
64
- function trailingUtcSixHourWindow(nowMs, bucketCount = 28) {
65
- const end = startOfUtcSixHour(nowMs);
66
- return {
67
- end,
68
- start: /* @__PURE__ */ new Date(end.getTime() - (bucketCount - 1) * SIX_HOUR_MS)
69
- };
70
- }
71
- /** Fill a fixed UTC day window from a sparse map. */
72
- function fillUtcDays(args) {
73
- const { end, start } = trailingUtcDayWindow(args.nowMs, args.count);
74
- const items = [];
75
- for (const cursor = new Date(start); cursor.getTime() <= end.getTime(); cursor.setUTCDate(cursor.getUTCDate() + 1)) {
76
- const date = utcDayKey(cursor);
77
- items.push(args.rows.get(date) ?? args.empty(date));
78
- }
79
- return items;
80
- }
81
- /** Fill a fixed UTC hour window from a sparse map. */
82
- function fillUtcHours(args) {
83
- const hourCount = args.count ?? 24;
84
- const { end, start } = trailingUtcHourWindow(args.nowMs, hourCount);
85
- const items = [];
86
- for (const cursor = new Date(start); cursor.getTime() <= end.getTime(); cursor.setTime(cursor.getTime() + HOUR_MS)) {
87
- const date = utcHourKey(cursor);
88
- items.push(args.rows.get(date) ?? args.empty(date));
89
- }
90
- return items;
91
- }
92
- /** Fill a fixed UTC 6-hour window from a map of known rows. */
93
- function fillUtcSixHours(args) {
94
- const bucketCount = args.count ?? 28;
95
- const { end, start } = trailingUtcSixHourWindow(args.nowMs, bucketCount);
96
- const items = [];
97
- for (const cursor = new Date(start); cursor.getTime() <= end.getTime(); cursor.setTime(cursor.getTime() + SIX_HOUR_MS)) {
98
- const date = utcSixHourKey(cursor);
99
- items.push(args.rows.get(date) ?? args.empty(date));
100
- }
101
- return items;
102
- }
103
- /**
104
- * Sum hour rows into trailing 6-hour buckets.
105
- * Adds number fields. Keeps other fields from the first row in the bucket.
106
- * Sets `date` to the 6-hour bucket key.
107
- */
108
- function sumUtcHoursIntoSixHours(args) {
109
- const bucketCount = args.count ?? 28;
110
- const bySix = /* @__PURE__ */ new Map();
111
- for (const hour of args.hours) {
112
- const key = utcSixHourKey(Date.parse(`${hour.date}:00:00.000Z`));
113
- const next = {
114
- ...bySix.get(key) ?? args.empty(key),
115
- date: key
116
- };
117
- for (const [field, value] of Object.entries(hour)) {
118
- if (field === "date") continue;
119
- if (typeof value === "number") {
120
- const prior = next[field];
121
- next[field] = (typeof prior === "number" ? prior : 0) + value;
122
- }
123
- }
124
- bySix.set(key, next);
125
- }
126
- return fillUtcSixHours({
127
- count: bucketCount,
128
- empty: args.empty,
129
- nowMs: args.nowMs,
130
- rows: bySix
131
- });
132
- }
133
- //#endregion
134
10
  //#region src/api/schema/code.ts
135
11
  const codeChangeSummarySchema = z.object({
136
12
  closed: z.number().int().nonnegative(),
@@ -241,9 +117,10 @@ function activityHours(hours, nowMs) {
241
117
  * Hour keys must be summed into 6-hour keys first.
242
118
  */
243
119
  function activitySixHours(hours, nowMs) {
120
+ const series = hours instanceof Map ? activityHours(hours, nowMs) : [...hours];
244
121
  return sumUtcHoursIntoSixHours({
245
122
  empty: emptyActivityDay,
246
- hours: hours instanceof Map ? activityHours(hours, nowMs) : [...hours],
123
+ hours: series,
247
124
  nowMs
248
125
  });
249
126
  }
@@ -556,4 +433,4 @@ const statsReportSchema = z.object({
556
433
  windowStart: z.string()
557
434
  }).strict();
558
435
  //#endregion
559
- export { sumUtcHoursIntoSixHours as $, actorProfileReportSchema as A, dailyConversationActivitySchema as B, createPersonalTokenBodySchema as C, personalTokenParamsSchema as D, personalTokenMetadataSchema as E, locationDirectoryReportSchema as F, codePersonReportSchema as G, codeChangeSummaryReportSchema as H, locationParamsSchema as I, HOUR_MS as J, codeRepositorySummarySchema as K, activityDays as L, personalSpendReportSchema as M, locationActivityDayReportSchema as N, revokePersonalTokenResponseSchema as O, locationDetailReportSchema as P, startOfUtcHour as Q, activityHours as R, scheduledAutomationSummarySchema as S, personalTokenListSchema as T, codeChangeSummarySchema as U, codeActivityDaySchema as V, codeOverviewReportSchema as W, fillUtcHours as X, fillUtcDays as Y, fillUtcSixHours as Z, automationRunListSchema as _, workspaceBodySchema as a, apiErrorSchema as at, automationSummarySchema as b, workspaceRepoSchema as c, automationExecutionSchema as d, trailingUtcDayWindow as et, automationExecutionStatusDaySchema as f, automationParamsSchema as g, automationListSchema as h, deleteWorkspaceResponseSchema as i, utcHourKey as it, personParamsSchema as j, actorDirectoryReportSchema as k, workspaceSchema as l, automationListQuerySchema as m, statsReportSchema as n, trailingUtcSixHourWindow as nt, workspaceListSchema as o, automationExecutionStatusSchema as p, DAY_MS as q, baselineSnapshotSchema as r, utcDayKey as rt, workspaceParamsSchema as s, statSchema as t, trailingUtcHourWindow as tt, automationExecutionListSchema as u, automationRunSchema as v, createdPersonalTokenSchema as w, eventAutomationSummarySchema as x, automationRunWindowsSchema as y, activitySixHours as z };
436
+ export { actorProfileReportSchema as A, dailyConversationActivitySchema as B, createPersonalTokenBodySchema as C, personalTokenParamsSchema as D, personalTokenMetadataSchema as E, locationDirectoryReportSchema as F, codePersonReportSchema as G, codeChangeSummaryReportSchema as H, locationParamsSchema as I, codeRepositorySummarySchema as K, activityDays as L, personalSpendReportSchema as M, locationActivityDayReportSchema as N, revokePersonalTokenResponseSchema as O, locationDetailReportSchema as P, activityHours as R, scheduledAutomationSummarySchema as S, personalTokenListSchema as T, codeChangeSummarySchema as U, codeActivityDaySchema as V, codeOverviewReportSchema as W, automationRunListSchema as _, workspaceBodySchema as a, automationSummarySchema as b, workspaceRepoSchema as c, automationExecutionSchema as d, automationExecutionStatusDaySchema as f, automationParamsSchema as g, automationListSchema as h, deleteWorkspaceResponseSchema as i, personParamsSchema as j, actorDirectoryReportSchema as k, workspaceSchema as l, automationListQuerySchema as m, statsReportSchema as n, workspaceListSchema as o, automationExecutionStatusSchema as p, apiErrorSchema as q, baselineSnapshotSchema as r, workspaceParamsSchema as s, statSchema as t, automationExecutionListSchema as u, automationRunSchema as v, createdPersonalTokenSchema as w, eventAutomationSummarySchema as x, automationRunWindowsSchema as y, activitySixHours as z };
@@ -1,5 +1,5 @@
1
- import { f as logWarn } from "./logging-D2YJv_PA.js";
2
- import { n as botConfig } from "./config-0_JixokJ.js";
1
+ import { f as logWarn } from "./logging-qmsMdU0y.js";
2
+ import { n as botConfig } from "./config-CGYv-YPE.js";
3
3
  const TITLE_PROMPTS = {
4
4
  conversation: [
5
5
  "Generate a concise 5-8 word conversation title from the first user message below.",
@@ -1,7 +1,7 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-B4FMCO8f.js";
2
- import { f as logWarn } from "./logging-D2YJv_PA.js";
2
+ import { f as logWarn } from "./logging-qmsMdU0y.js";
3
3
  import { s as skillRoots } from "./package-discovery-7a9YqLhE.js";
4
- import { n as pluginCatalogRuntime } from "./catalog-runtime-D1v0KsgY.js";
4
+ import { n as pluginCatalogRuntime } from "./catalog-runtime-XH_LFA_7.js";
5
5
  import path from "node:path";
6
6
  import { z } from "zod";
7
7
  import fs from "node:fs/promises";
@@ -1,6 +1,6 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-B4FMCO8f.js";
2
- import { C as toolInvocationDestination, y as actorFromRun } from "./agent-runner-DMMa36Zl.js";
3
- import { n as createAndEnqueueAgentInvocation } from "./work-DCwaUeWu.js";
2
+ import { C as toolInvocationDestination, y as actorFromRun } from "./agent-runner-D0ImXS7U.js";
3
+ import { n as createAndEnqueueAgentInvocation } from "./work-Citqpnfc.js";
4
4
  //#region src/chat/agent-invocations/spawn.ts
5
5
  var spawn_exports = /* @__PURE__ */ __exportAll({ bindSpawnAgent: () => bindSpawnAgent });
6
6
  /** Bind a Run's Actor and credentials to new Agent invocations. */
@@ -1,10 +1,12 @@
1
- import { F as isRecord$1, I as toOptionalNumber, L as toOptionalString } from "./logging-D2YJv_PA.js";
2
- import { a as getChatConfig } from "./config-0_JixokJ.js";
1
+ import { F as isRecord$1, I as toOptionalNumber, L as toOptionalString } from "./logging-qmsMdU0y.js";
2
+ import { a as getChatConfig } from "./config-CGYv-YPE.js";
3
3
  import { _ as parseSlackMessageTs, d as parseStoredSlackActor, h as parseSlackTeamId, p as parseSlackChannelId } from "./context-Bplcgypl.js";
4
- import { Gt as getDb, J as withSlackRetries, U as getSlackClient, Wt as getConversationStore, fn as sameDestination, pt as JUNIOR_THREAD_STATE_TTL_MS, u as getPlugins, un as parseDestination } from "./agent-hooks-kjLDY-Aa.js";
4
+ import { Gt as getDb, J as withSlackRetries, U as getSlackClient, Wt as getConversationStore, fn as sameDestination, ht as getDashboardTaskLink, pt as JUNIOR_THREAD_STATE_TTL_MS, u as getPlugins, un as parseDestination } from "./agent-hooks-DkriF84n.js";
5
5
  import { n as juniorDestinations } from "./destinations-BeBiJeEM.js";
6
- import { E as juniorConversations, a as juniorSchedulerRuns, c as juniorStats, l as juniorEventAutomations, o as juniorSchedulerTasks, w as juniorAttachments } from "./executor-CmZKtNpH.js";
7
- import { C as getDefaultRedisStateAdapterFor, w as getStateAdapter } from "./profile-C3TEFAVI.js";
6
+ import { E as juniorConversations, a as juniorSchedulerRuns, c as juniorStats, l as juniorEventAutomations, o as juniorSchedulerTasks, w as juniorAttachments } from "./executor-BLBZ-UB8.js";
7
+ import { j as automationCardSchema } from "./conversation-BBDt88di.js";
8
+ import { t as fallbackShortTitle } from "./short-title-CB2fxEyx.js";
9
+ import { C as getDefaultRedisStateAdapterFor, w as getStateAdapter } from "./profile-DbG8AlNd.js";
8
10
  import "./vercel-queue-DIkVcfK4.js";
9
11
  import { z } from "zod";
10
12
  import { createHash, randomUUID } from "node:crypto";
@@ -1640,21 +1642,28 @@ const eventAutomationTriggerSchema = z.object({
1640
1642
  identifier: z.string().min(1).max(300),
1641
1643
  resourceType: z.string().min(1)
1642
1644
  }).strict();
1645
+ /** Event automations target a Slack channel or DM, never a message thread. */
1646
+ const eventAutomationDestinationSchema = slackDestinationSchema.omit({ threadTs: true });
1647
+ const eventAutomationOutcomeSchema = taskOutcomeSchema.extend({ destination: eventAutomationDestinationSchema });
1643
1648
  /** Validate one persisted event automation. */
1644
1649
  const eventAutomationSchema = z.object({
1645
1650
  id: z.string().min(1),
1646
1651
  createdAtMs: z.number().finite(),
1647
1652
  createdBy: eventAutomationPrincipalSchema,
1648
1653
  credentialMode: z.enum(["system", "creator"]),
1649
- destination: slackDestinationSchema,
1654
+ destination: eventAutomationDestinationSchema,
1650
1655
  destinationVisibility: destinationVisibilitySchema,
1651
1656
  /** Explicit visible effects after successful work. An empty list is silent. */
1652
- outcomes: z.array(taskOutcomeSchema).max(5),
1657
+ outcomes: z.array(eventAutomationOutcomeSchema).max(5),
1653
1658
  task: z.object({ text: z.string().min(1) }).strict(),
1654
1659
  trigger: eventAutomationTriggerSchema
1655
1660
  }).strict();
1656
1661
  //#endregion
1657
1662
  //#region src/chat/event-automations/store.ts
1663
+ const retainedEventAutomationSchema = eventAutomationSchema.extend({
1664
+ destination: slackDestinationSchema,
1665
+ outcomes: z.array(taskOutcomeSchema).max(5)
1666
+ });
1658
1667
  /** JSON task payload must not carry SQL-backed columns. */
1659
1668
  function eventAutomationJsonPayload(task) {
1660
1669
  const { status: _status, title: _title, ...payload } = task;
@@ -1667,10 +1676,19 @@ function parseTask(row) {
1667
1676
  action: "send_message",
1668
1677
  destination: raw.destination
1669
1678
  }];
1670
- const payload = eventAutomationSchema.parse(raw);
1679
+ const retained = retainedEventAutomationSchema.parse(raw);
1680
+ const { threadTs: _threadTs, ...destination } = retained.destination;
1671
1681
  const title = row.title?.trim();
1672
1682
  return {
1673
- ...payload,
1683
+ ...retained,
1684
+ destination,
1685
+ outcomes: retained.outcomes.map((outcome) => {
1686
+ const { threadTs: _threadTs, ...destination } = outcome.destination;
1687
+ return {
1688
+ ...outcome,
1689
+ destination
1690
+ };
1691
+ }),
1674
1692
  status: row.status === "deleted" ? "deleted" : "active",
1675
1693
  ...title ? { title } : void 0
1676
1694
  };
@@ -1885,6 +1903,7 @@ function moveTaskOutcomes(outcomes, currentDestination, nextDestination) {
1885
1903
  const compactEventAutomationResultSchema = z.object({
1886
1904
  id: z.string().min(1),
1887
1905
  title: z.string().min(1).nullable(),
1906
+ dashboardUrl: z.string().url().nullable(),
1888
1907
  instruction: z.string().min(1),
1889
1908
  trigger: z.object({
1890
1909
  namespace: z.string().min(1),
@@ -1910,7 +1929,10 @@ const compactEventAutomationResultSchema = z.object({
1910
1929
  }).strict()
1911
1930
  }).strict();
1912
1931
  /** Validate one successful event-automation mutation result. */
1913
- const eventAutomationToolResultSchema = juniorToolOutputSchema.extend({ automation: compactEventAutomationResultSchema }).strict();
1932
+ const eventAutomationToolResultSchema = juniorToolOutputSchema.extend({
1933
+ automation: compactEventAutomationResultSchema,
1934
+ cards: z.array(automationCardSchema)
1935
+ }).strict();
1914
1936
  /** Validate one successful event-automation list result. */
1915
1937
  const eventAutomationListToolResultSchema = juniorToolOutputSchema.extend({
1916
1938
  automations: z.array(compactEventAutomationResultSchema),
@@ -1946,8 +1968,7 @@ function requireEventAutomationSlackContext(context) {
1946
1968
  destination: {
1947
1969
  platform: "slack",
1948
1970
  teamId: context.source.teamId,
1949
- channelId: context.source.channelId,
1950
- threadTs: context.source.threadTs ?? context.source.messageTs
1971
+ channelId: context.source.channelId
1951
1972
  },
1952
1973
  source: context.source
1953
1974
  };
@@ -1981,6 +2002,7 @@ function compactEventAutomation(task, catalog, requesterSlackUserId) {
1981
2002
  return compactEventAutomationResultSchema.parse({
1982
2003
  id: task.id,
1983
2004
  title: task.title?.trim() || null,
2005
+ dashboardUrl: getDashboardTaskLink(task.id) ?? null,
1984
2006
  instruction: task.task.text,
1985
2007
  trigger: {
1986
2008
  namespace: task.trigger.namespace,
@@ -2008,7 +2030,24 @@ function compactEventAutomation(task, catalog, requesterSlackUserId) {
2008
2030
  }
2009
2031
  /** Return the standard successful event-automation tool result. */
2010
2032
  function eventAutomationToolResult(task, catalog, requesterSlackUserId) {
2011
- return { automation: compactEventAutomation(task, catalog, requesterSlackUserId) };
2033
+ const automation = compactEventAutomation(task, catalog, requesterSlackUserId);
2034
+ const filters = Object.entries(task.trigger.match ?? {}).map(([key, value]) => `${key} = ${JSON.stringify(value)}`);
2035
+ return {
2036
+ automation,
2037
+ cards: [{
2038
+ kind: "automation",
2039
+ id: task.id,
2040
+ title: automation.title ?? fallbackShortTitle(task.task.text, "Event automation"),
2041
+ url: automation.dashboardUrl,
2042
+ instruction: task.task.text,
2043
+ trigger: [
2044
+ task.trigger.label,
2045
+ task.trigger.events.join(", "),
2046
+ ...filters
2047
+ ].join(" · "),
2048
+ warning: !automation.trigger.available ? "Trigger unavailable. This automation cannot receive events." : null
2049
+ }]
2050
+ };
2012
2051
  }
2013
2052
  //#endregion
2014
2053
  //#region src/chat/scheduled-automations/types.ts
@@ -1,6 +1,6 @@
1
- import { f as logWarn } from "./logging-D2YJv_PA.js";
1
+ import { f as logWarn } from "./logging-qmsMdU0y.js";
2
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 { o as runWithTurnRequestDeadline } from "./job-queue-B1k3woMW.js";
3
+ import { o as runWithTurnRequestDeadline } from "./job-queue-_8gxwDzt.js";
4
4
  import { z } from "zod";
5
5
  import { createHash } from "node:crypto";
6
6
  import { handleCallback, registerDevConsumer } from "@vercel/queue";
@@ -110,7 +110,7 @@ function pluginTaskCallback() {
110
110
  maxDeliveries: PLUGIN_TASK_MAX_DELIVERIES,
111
111
  onRejected: logPluginTaskQueueMessageRejected,
112
112
  run: async (message) => {
113
- const { processPluginTask } = await import("./task-runner-6tzKHNbM.js").then((n) => n.r);
113
+ const { processPluginTask } = await import("./task-runner-4rCppQMo.js").then((n) => n.r);
114
114
  await processPluginTask(message);
115
115
  },
116
116
  topic: PLUGIN_TASK_QUEUE_TOPIC,