@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,298 @@
1
+ import { z } from "zod";
2
+ import "@sentry/junior-plugin-api";
3
+ //#region src/chat/slack/timestamp.ts
4
+ /** Native Slack message timestamp, safe to pass as Slack Web API `message_ts`. */
5
+ const slackMessageTsSchema = z.string().trim().regex(/^\d+(?:\.\d+)?$/).brand();
6
+ /** Parse a native Slack message timestamp from untrusted message metadata. */
7
+ function parseSlackMessageTs(value) {
8
+ const parsed = slackMessageTsSchema.safeParse(value);
9
+ return parsed.success ? parsed.data : void 0;
10
+ }
11
+ //#endregion
12
+ //#region src/chat/slack/ids.ts
13
+ const slackChannelIdSchema = z.string().regex(/^[CDG][A-Z0-9]+$/).brand();
14
+ const slackTeamIdSchema = z.string().regex(/^T[A-Z0-9]+$/).brand();
15
+ const slackUserIdSchema = z.string().regex(/^[UW][A-Z0-9]+$/).brand();
16
+ const SLACK_CHANNEL_MENTION_RE = /^<#([CDG][A-Z0-9]+)(?:\|[^>]*)?>$/;
17
+ function slackChannelReferenceCandidate(value) {
18
+ const trimmed = value.trim();
19
+ if (!trimmed.startsWith("slack:")) return trimmed;
20
+ const parts = trimmed.split(":");
21
+ if (parts.length === 2) return parts[1]?.trim() ?? "";
22
+ if (parts.length === 3 && parseSlackMessageTs(parts[2])) return parts[1]?.trim() ?? "";
23
+ return "";
24
+ }
25
+ /** Parse an exact Slack channel/conversation ID from untrusted input. */
26
+ function parseSlackChannelId(value) {
27
+ if (typeof value !== "string") return void 0;
28
+ const parsed = slackChannelIdSchema.safeParse(value.trim());
29
+ return parsed.success ? parsed.data : void 0;
30
+ }
31
+ /**
32
+ * Parse a channel id from common tool/model reference forms.
33
+ *
34
+ * Accepts exact ids (`C123`), Slack mentions (`<#C123>` / `<#C123|name>`),
35
+ * and Junior slack references (`slack:C123`, `slack:C123:ts`). Plain channel
36
+ * names are not ids and are rejected here.
37
+ */
38
+ function parseSlackChannelReferenceId(value) {
39
+ if (typeof value !== "string") return void 0;
40
+ const trimmed = value.trim();
41
+ const mentionMatch = SLACK_CHANNEL_MENTION_RE.exec(trimmed);
42
+ if (mentionMatch?.[1]) return parseSlackChannelId(mentionMatch[1]);
43
+ return parseSlackChannelId(slackChannelReferenceCandidate(trimmed));
44
+ }
45
+ /** Parse a Slack workspace/team ID from untrusted metadata. */
46
+ function parseSlackTeamId(value) {
47
+ if (typeof value !== "string") return void 0;
48
+ const parsed = slackTeamIdSchema.safeParse(value.trim());
49
+ return parsed.success ? parsed.data : void 0;
50
+ }
51
+ /** Parse a Slack user ID from untrusted metadata. */
52
+ function parseSlackUserId(value) {
53
+ if (typeof value !== "string") return void 0;
54
+ const parsed = slackUserIdSchema.safeParse(value.trim());
55
+ return parsed.success ? parsed.data : void 0;
56
+ }
57
+ //#endregion
58
+ //#region src/chat/actor.ts
59
+ /**
60
+ * Canonical actor identity.
61
+ *
62
+ * Runtime actors are platform-scoped actors. Stored Slack actor parsing
63
+ * remains explicit so durable conversation metadata is not repaired on read.
64
+ */
65
+ const SLACK_USER_ID_DISPLAY_PATTERN = /^[UW][A-Z0-9]{5,}$/;
66
+ const EMAIL_PATTERN = /^[^\s@<>]+@[^\s@<>]+\.[^\s@<>]+$/;
67
+ const exactStoredStringSchema = z.string().min(1).refine((value) => value === value.trim());
68
+ const storedSlackActorSchema = z.object({
69
+ email: exactStoredStringSchema.optional(),
70
+ fullName: exactStoredStringSchema.optional(),
71
+ platform: z.literal("slack").optional(),
72
+ slackUserId: exactStoredStringSchema.optional(),
73
+ slackUserName: exactStoredStringSchema.optional(),
74
+ teamId: exactStoredStringSchema.optional()
75
+ }).strict();
76
+ /** Return whether an actor is a platform-scoped user actor. */
77
+ function isUserActor(actor) {
78
+ return Boolean(actor && "userId" in actor);
79
+ }
80
+ function clean(value) {
81
+ const trimmed = value?.trim();
82
+ return trimmed ? trimmed : void 0;
83
+ }
84
+ function isSyntheticActorUserId(value) {
85
+ return value.toLowerCase() === "unknown";
86
+ }
87
+ function isSlackUserId(value) {
88
+ return SLACK_USER_ID_DISPLAY_PATTERN.test(value);
89
+ }
90
+ function cleanActorDisplayName(value, userId) {
91
+ const displayName = clean(value);
92
+ if (!displayName) return;
93
+ if (displayName.toLowerCase() === "unknown") return;
94
+ if (userId && displayName === userId) return;
95
+ return isSlackUserId(displayName) ? void 0 : displayName;
96
+ }
97
+ function cleanActorEmail(value) {
98
+ const email = clean(value);
99
+ return email && EMAIL_PATTERN.test(email) ? email : void 0;
100
+ }
101
+ /** Keep actor ids exact at platform boundaries before they enter owned state. */
102
+ function parseActorUserId(value) {
103
+ if (typeof value !== "string" || value.length === 0) return;
104
+ if (value !== value.trim() || isSyntheticActorUserId(value)) return;
105
+ return value;
106
+ }
107
+ /** Assert persisted actor ids without read-side repair. */
108
+ function isActorUserId(value) {
109
+ return parseActorUserId(value) === value;
110
+ }
111
+ /** Build Junior's canonical platform actor from exact actor ids and profile data. */
112
+ function createActor(input, context) {
113
+ const platform = context.platform ?? input?.platform;
114
+ if (!platform) return;
115
+ const contextUserId = parseActorUserId(context.userId);
116
+ if (context.userId !== void 0 && !contextUserId) return;
117
+ const inputUserId = parseActorUserId(input?.userId);
118
+ if (input?.userId !== void 0 && !inputUserId) return;
119
+ const actorUserId = contextUserId ?? inputUserId;
120
+ if (!actorUserId) return;
121
+ const contextTeamId = parseSlackTeamId(context.teamId);
122
+ if (context.teamId !== void 0 && !contextTeamId) return;
123
+ const inputTeamId = parseSlackTeamId(input?.teamId);
124
+ if (input?.teamId !== void 0 && !inputTeamId) return;
125
+ const actorTeamId = contextTeamId ?? inputTeamId;
126
+ if (platform === "slack" && !actorTeamId) return;
127
+ const canUseInputProfile = (!contextUserId || !inputUserId || contextUserId === inputUserId) && (platform !== "slack" || !contextTeamId || !inputTeamId || contextTeamId === inputTeamId);
128
+ const actor = {
129
+ ...canUseInputProfile && cleanActorEmail(input?.email) ? { email: cleanActorEmail(input?.email) } : void 0,
130
+ ...canUseInputProfile && cleanActorDisplayName(input?.fullName, actorUserId) ? { fullName: cleanActorDisplayName(input?.fullName, actorUserId) } : void 0,
131
+ platform,
132
+ userId: actorUserId,
133
+ ...canUseInputProfile && cleanActorDisplayName(input?.userName, actorUserId) ? { userName: cleanActorDisplayName(input?.userName, actorUserId) } : void 0
134
+ };
135
+ if (platform === "slack") return {
136
+ ...actor,
137
+ platform,
138
+ teamId: actorTeamId
139
+ };
140
+ return {
141
+ ...actor,
142
+ platform
143
+ };
144
+ }
145
+ /** Build Junior's canonical actor from Slack profile data. */
146
+ function createSlackActor(teamId, userId, profile) {
147
+ const actorUserId = parseActorUserId(userId);
148
+ const actorTeamId = parseSlackTeamId(teamId);
149
+ if (!actorTeamId || !actorUserId) throw new Error("Slack actor requires team and user ids");
150
+ const actor = createActor({
151
+ email: profile?.email,
152
+ fullName: profile?.fullName,
153
+ platform: "slack",
154
+ teamId: actorTeamId,
155
+ userId: actorUserId,
156
+ userName: profile?.userName
157
+ }, {
158
+ teamId: actorTeamId,
159
+ userId: actorUserId
160
+ });
161
+ if (!actor || actor.platform !== "slack") throw new Error("Slack actor requires team and user ids");
162
+ return actor;
163
+ }
164
+ /** Parse a serialized Slack actor that crossed a runtime boundary. */
165
+ function parseStoredSlackActor(value) {
166
+ const parsed = storedSlackActorSchema.safeParse(value);
167
+ if (!parsed.success) return;
168
+ if (parsed.data.slackUserId !== void 0 && !parseActorUserId(parsed.data.slackUserId)) return;
169
+ if (parsed.data.teamId !== void 0 && !parseSlackTeamId(parsed.data.teamId)) return;
170
+ if ((parsed.data.platform !== void 0 || parsed.data.teamId !== void 0) && (!parsed.data.platform || !parsed.data.teamId)) return;
171
+ return parsed.data;
172
+ }
173
+ /** Convert a runtime Slack actor into its durable session shape. */
174
+ function toStoredSlackActor(actor) {
175
+ return {
176
+ ...actor.email ? { email: actor.email } : void 0,
177
+ ...actor.fullName ? { fullName: actor.fullName } : void 0,
178
+ platform: actor.platform,
179
+ slackUserId: actor.userId,
180
+ ...actor.userName ? { slackUserName: actor.userName } : void 0,
181
+ teamId: actor.teamId
182
+ };
183
+ }
184
+ /**
185
+ * Resolve a Slack resume actor from stored profile data and the active actor.
186
+ *
187
+ * TODO(dcramer): Require Actor and remove ID-only construction after no
188
+ * deployed Turn cursor can omit Actor.
189
+ */
190
+ function createSlackResumeActor(args) {
191
+ if (args.actor) {
192
+ if (args.actor.platform !== "slack" || args.actor.teamId !== args.teamId || args.actor.userId !== args.userId) throw new Error("Stored Slack actor did not match resume actor");
193
+ }
194
+ const actor = createActor(args.actor, {
195
+ platform: "slack",
196
+ teamId: args.teamId,
197
+ userId: args.userId
198
+ });
199
+ if (!actor || actor.platform !== "slack") throw new Error("Slack actor requires team and user ids");
200
+ return actor;
201
+ }
202
+ //#endregion
203
+ //#region src/chat/credentials/context.ts
204
+ const exactActorIdSchema = z.string().refine((value) => parseActorUserId(value) === value);
205
+ const exactNonBlankStringSchema = z.string().min(1).refine((value) => value === value.trim());
206
+ const slackDirectCredentialSubjectBindingSchema = z.object({
207
+ type: z.literal("slack-direct-conversation"),
208
+ teamId: z.string().min(1),
209
+ channelId: z.string().min(1),
210
+ signature: z.string().min(1)
211
+ }).strict();
212
+ const scheduledTaskCredentialSubjectBindingSchema = z.object({
213
+ type: z.literal("scheduled-task"),
214
+ plugin: z.string().min(1),
215
+ taskId: exactNonBlankStringSchema,
216
+ signature: z.string().min(1)
217
+ }).strict();
218
+ const eventTaskCredentialSubjectBindingSchema = z.object({
219
+ type: z.literal("event-task"),
220
+ plugin: z.string().min(1),
221
+ taskId: exactNonBlankStringSchema,
222
+ signature: z.string().min(1)
223
+ }).strict();
224
+ z.discriminatedUnion("type", [
225
+ slackDirectCredentialSubjectBindingSchema,
226
+ scheduledTaskCredentialSubjectBindingSchema,
227
+ eventTaskCredentialSubjectBindingSchema
228
+ ]);
229
+ const credentialUserActorSchema = z.object({
230
+ type: z.literal("user"),
231
+ userId: exactActorIdSchema
232
+ }).strict();
233
+ const credentialSystemActorSchema = z.object({
234
+ platform: z.literal("system"),
235
+ name: exactActorIdSchema
236
+ }).strict();
237
+ const credentialSubjectSchema = z.discriminatedUnion("allowedWhen", [
238
+ z.object({
239
+ type: z.literal("user"),
240
+ userId: exactActorIdSchema,
241
+ allowedWhen: z.literal("private-direct-conversation"),
242
+ binding: slackDirectCredentialSubjectBindingSchema
243
+ }).strict(),
244
+ z.object({
245
+ type: z.literal("user"),
246
+ userId: exactActorIdSchema,
247
+ allowedWhen: z.literal("scheduled-task"),
248
+ taskId: exactNonBlankStringSchema,
249
+ binding: scheduledTaskCredentialSubjectBindingSchema
250
+ }).strict().refine((subject) => subject.binding.taskId === subject.taskId, {
251
+ message: "Scheduled task credential subject requires task binding",
252
+ path: ["binding"]
253
+ }),
254
+ z.object({
255
+ type: z.literal("user"),
256
+ userId: exactActorIdSchema,
257
+ allowedWhen: z.literal("event-task"),
258
+ taskId: exactNonBlankStringSchema,
259
+ binding: eventTaskCredentialSubjectBindingSchema
260
+ }).strict().refine((subject) => subject.binding.taskId === subject.taskId, {
261
+ message: "Event task credential subject requires task binding",
262
+ path: ["binding"]
263
+ })
264
+ ]);
265
+ const credentialContextSchema = z.union([z.object({ actor: credentialUserActorSchema }).strict(), z.object({
266
+ actor: credentialSystemActorSchema,
267
+ subject: credentialSubjectSchema.optional()
268
+ }).strict()]);
269
+ /**
270
+ * Build credential authority from the run actor.
271
+ *
272
+ * `actor` is the rich execution principal. This projects the credential stub
273
+ * tools/auth need from it:
274
+ * - user actor → `{ actor: { type: "user", userId } }`
275
+ * - system actor → `{ actor: systemActor, subject? }`
276
+ *
277
+ * They only diverge when a system run carries an explicit delegated `subject`
278
+ * (scheduled/event-task creator credentials). Callers should set `actor` first,
279
+ * then derive this — do not hand-build parallel shapes.
280
+ */
281
+ function credentialContextForActor(actor, subject) {
282
+ if (actor.platform === "system") return subject ? {
283
+ actor,
284
+ subject
285
+ } : { actor };
286
+ if (subject) throw new TypeError("Delegated credential subjects require a system actor");
287
+ return { actor: {
288
+ type: "user",
289
+ userId: actor.userId
290
+ } };
291
+ }
292
+ /** Return the user whose OAuth token may satisfy this credential request. */
293
+ function credentialUserSubjectId(context) {
294
+ if ("type" in context.actor) return context.actor.userId;
295
+ return "subject" in context ? context.subject?.userId : void 0;
296
+ }
297
+ //#endregion
298
+ export { parseSlackMessageTs as _, createActor as a, isActorUserId as c, parseStoredSlackActor as d, toStoredSlackActor as f, parseSlackUserId as g, parseSlackTeamId as h, credentialUserSubjectId as i, isUserActor as l, parseSlackChannelReferenceId as m, credentialContextSchema as n, createSlackActor as o, parseSlackChannelId as p, credentialSubjectSchema as r, createSlackResumeActor as s, credentialContextForActor as t, parseActorUserId as u };
@@ -0,0 +1,182 @@
1
+ import { f as logWarn } from "./logging-BzAk1S_s.js";
2
+ import { AsyncLocalStorage } from "node:async_hooks";
3
+ //#region src/chat/conversation-privacy.ts
4
+ const SAFE_METADATA_KEY_LIMIT = 20;
5
+ const conversationPrivacyStorage = new AsyncLocalStorage();
6
+ /**
7
+ * Resolve whether a Conversation may expose full transcript and tool data.
8
+ *
9
+ * Read visibility from the stored Conversation. If it is missing, warn and
10
+ * treat the Conversation as private. Do not infer visibility from identifiers.
11
+ */
12
+ function resolveConversationPrivacy(input) {
13
+ if (input.visibility === void 0) logWarn("conversation.visibility.defaulted");
14
+ return input.visibility === "public" ? "public" : "private";
15
+ }
16
+ /** Return whether a public Conversation may expose transcript and tool data. */
17
+ function canExposeConversationPayload(input) {
18
+ return resolveConversationPrivacy(input) === "public";
19
+ }
20
+ /** Return privacy for the current agent Turn. */
21
+ function getCurrentConversationPrivacy() {
22
+ return conversationPrivacyStorage.getStore();
23
+ }
24
+ /** Bind one conversation privacy mode to all async work in a turn. */
25
+ function runWithConversationPrivacy(privacy, callback) {
26
+ return conversationPrivacyStorage.run(privacy, callback);
27
+ }
28
+ function payloadType(payload) {
29
+ return Array.isArray(payload) ? "array" : typeof payload;
30
+ }
31
+ function payloadKeys(payload) {
32
+ if (!payload || typeof payload !== "object" || Array.isArray(payload)) return;
33
+ const keys = Object.keys(payload).slice(0, SAFE_METADATA_KEY_LIMIT);
34
+ return keys.length > 0 ? keys : void 0;
35
+ }
36
+ function serializedLength(payload) {
37
+ return (typeof payload === "string" ? payload : JSON.stringify(payload))?.length ?? 0;
38
+ }
39
+ /** Convert an arbitrary payload into safe structured metadata for trace data fields. */
40
+ function toGenAiPayloadMetadata(payload) {
41
+ const base = {
42
+ type: payloadType(payload),
43
+ chars: serializedLength(payload)
44
+ };
45
+ if (!payload || typeof payload !== "object" || Array.isArray(payload)) return base;
46
+ const keys = payloadKeys(payload);
47
+ return {
48
+ ...base,
49
+ ...keys ? { keys } : void 0
50
+ };
51
+ }
52
+ /** Convert an arbitrary payload into safe flattened trace attributes. */
53
+ function toGenAiPayloadTraceAttributes(prefix, payload) {
54
+ const size = serializedLength(payload);
55
+ const attributes = {
56
+ [`${prefix}.type`]: payloadType(payload),
57
+ [`${prefix}.size_chars`]: size,
58
+ [`${prefix}.size`]: size
59
+ };
60
+ const keys = payloadKeys(payload);
61
+ if (keys) attributes[`${prefix}.keys`] = keys;
62
+ return attributes;
63
+ }
64
+ function summarizeContent(content) {
65
+ if (typeof content === "string") return {
66
+ chars: content.length,
67
+ partTypes: ["text"]
68
+ };
69
+ if (!Array.isArray(content)) return {
70
+ chars: serializedLength(content),
71
+ partTypes: [payloadType(content)]
72
+ };
73
+ let chars = 0;
74
+ const partTypes = /* @__PURE__ */ new Set();
75
+ for (const part of content) {
76
+ if (!part || typeof part !== "object") {
77
+ chars += serializedLength(part);
78
+ partTypes.add(payloadType(part));
79
+ continue;
80
+ }
81
+ const record = part;
82
+ const type = canonicalContentPartType(typeof record.type === "string" ? record.type : "unknown");
83
+ partTypes.add(type);
84
+ if (typeof record.text === "string") chars += record.text.length;
85
+ else if (typeof record.thinking === "string") chars += record.thinking.length;
86
+ else if (typeof record.data === "string") chars += record.data.length;
87
+ else chars += serializedLength(part);
88
+ }
89
+ return {
90
+ chars,
91
+ partTypes: [...partTypes]
92
+ };
93
+ }
94
+ function normalizeFinishReason(reason) {
95
+ return reason === "toolUse" ? "tool_call" : reason;
96
+ }
97
+ function canonicalContentPartType(type) {
98
+ if (type === "thinking") return "reasoning";
99
+ if (type === "toolCall") return "tool_call";
100
+ return type;
101
+ }
102
+ function toCanonicalPart(part) {
103
+ if (part.type === "text") return {
104
+ type: "text",
105
+ content: part.text
106
+ };
107
+ if (part.type === "thinking") {
108
+ if (part.redacted) return;
109
+ return {
110
+ type: "reasoning",
111
+ content: part.thinking
112
+ };
113
+ }
114
+ if (part.type === "toolCall") return {
115
+ type: "tool_call",
116
+ id: part.id,
117
+ name: part.name,
118
+ arguments: part.arguments
119
+ };
120
+ }
121
+ function toCanonicalParts(parts) {
122
+ return parts.map(toCanonicalPart).filter((part) => part !== void 0);
123
+ }
124
+ /**
125
+ * Map a pi-ai AssistantMessage to the canonical gen_ai.output.messages shape:
126
+ * `{ role, parts: [...], finish_reason }` — drops provider noise fields.
127
+ */
128
+ function toCanonicalOutputMessage(message) {
129
+ return {
130
+ role: "assistant",
131
+ parts: toCanonicalParts(message.content),
132
+ finish_reason: normalizeFinishReason(message.stopReason)
133
+ };
134
+ }
135
+ /**
136
+ * Map a pi-ai Message (user/assistant/toolResult) to the canonical
137
+ * gen_ai.input.messages shape: `{ role, parts: [...] }`.
138
+ */
139
+ function toCanonicalInputMessage(message) {
140
+ if (message.role === "user") return {
141
+ role: "user",
142
+ parts: typeof message.content === "string" ? [{
143
+ type: "text",
144
+ content: message.content
145
+ }] : toCanonicalParts(message.content)
146
+ };
147
+ if (message.role === "toolResult") return {
148
+ role: "tool",
149
+ parts: [{
150
+ type: "tool_call_response",
151
+ id: message.toolCallId,
152
+ response: toCanonicalParts(message.content)
153
+ }]
154
+ };
155
+ return toCanonicalOutputMessage(message);
156
+ }
157
+ /** Summarize a message list without exposing raw message content. */
158
+ function toGenAiMessagesTraceAttributes(prefix, messages) {
159
+ let contentChars = 0;
160
+ const roles = /* @__PURE__ */ new Set();
161
+ const partTypes = /* @__PURE__ */ new Set();
162
+ for (const message of messages) {
163
+ if (!message || typeof message !== "object") {
164
+ contentChars += serializedLength(message);
165
+ continue;
166
+ }
167
+ const record = message;
168
+ if (typeof record.role === "string") roles.add(record.role);
169
+ const summary = summarizeContent(record.content);
170
+ contentChars += summary.chars;
171
+ for (const partType of summary.partTypes) partTypes.add(partType);
172
+ }
173
+ return {
174
+ [`${prefix}.message_count`]: messages.length,
175
+ [`${prefix}.content_chars`]: contentChars,
176
+ [`${prefix}.messages.size`]: contentChars,
177
+ ...roles.size > 0 ? { [`${prefix}.roles`]: [...roles] } : void 0,
178
+ ...partTypes.size > 0 ? { [`${prefix}.part_types`]: [...partTypes] } : void 0
179
+ };
180
+ }
181
+ //#endregion
182
+ export { toCanonicalInputMessage as a, toGenAiPayloadMetadata as c, runWithConversationPrivacy as i, toGenAiPayloadTraceAttributes as l, getCurrentConversationPrivacy as n, toCanonicalOutputMessage as o, resolveConversationPrivacy as r, toGenAiMessagesTraceAttributes as s, canExposeConversationPayload as t };
@@ -0,0 +1,51 @@
1
+ //#region src/chat/local/conversation-work.ts
2
+ /**
3
+ * Run local conversation work in this process and wait for every accepted wake.
4
+ *
5
+ * Wakes start on a later event-loop turn so their producer can persist the
6
+ * accepted marker first. Idempotent, delayed, and follow-up wakes remain
7
+ * tracked so CLI shutdown cannot abandon accepted child work.
8
+ */
9
+ function createLocalConversationWork(processMessage) {
10
+ const acceptedWakeIds = /* @__PURE__ */ new Map();
11
+ const pending = /* @__PURE__ */ new Set();
12
+ let firstError;
13
+ let nextWakeId = 1;
14
+ function schedule(message, options) {
15
+ const delayMs = Math.max(0, options?.delayMs ?? 0);
16
+ let work;
17
+ work = (async () => {
18
+ await new Promise((resolve) => {
19
+ setTimeout(resolve, delayMs);
20
+ });
21
+ await processMessage(message);
22
+ })().catch((error) => {
23
+ firstError ??= error;
24
+ }).finally(() => {
25
+ pending.delete(work);
26
+ });
27
+ pending.add(work);
28
+ }
29
+ return {
30
+ queue: { async send(message, options) {
31
+ const idempotencyKey = options?.idempotencyKey;
32
+ const acceptedWakeId = idempotencyKey ? acceptedWakeIds.get(idempotencyKey) : void 0;
33
+ if (acceptedWakeId) return { messageId: acceptedWakeId };
34
+ const messageId = `local-conversation-work:${nextWakeId}`;
35
+ nextWakeId += 1;
36
+ if (idempotencyKey) acceptedWakeIds.set(idempotencyKey, messageId);
37
+ schedule(message, options);
38
+ return { messageId };
39
+ } },
40
+ async drain() {
41
+ while (pending.size > 0) await Promise.all(pending);
42
+ if (firstError !== void 0) {
43
+ const error = firstError;
44
+ firstError = void 0;
45
+ throw error;
46
+ }
47
+ }
48
+ };
49
+ }
50
+ //#endregion
51
+ export { createLocalConversationWork };