@sentry/junior 0.203.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 +8 -8
  92. package/dist/agent-hooks-GB2VPTNA.js +0 -51
  93. package/dist/catalog-runtime-UBLIWD3O.js +0 -14
  94. package/dist/chunk-2LYHWMR4.js +0 -46
  95. package/dist/chunk-352OWAZH.js +0 -320
  96. package/dist/chunk-3Y47VMHV.js +0 -6
  97. package/dist/chunk-3YJSKOWF.js +0 -164
  98. package/dist/chunk-4KSSKTQ5.js +0 -229
  99. package/dist/chunk-4UO6FK4G.js +0 -64
  100. package/dist/chunk-5AHX53NQ.js +0 -717
  101. package/dist/chunk-5J3E5FWA.js +0 -700
  102. package/dist/chunk-5PDAG6O3.js +0 -206
  103. package/dist/chunk-6Y5B5PEX.js +0 -80
  104. package/dist/chunk-7GWQ5S5R.js +0 -2086
  105. package/dist/chunk-7H2VZTWN.js +0 -103
  106. package/dist/chunk-7NL7T6VU.js +0 -406
  107. package/dist/chunk-A5L27LE4.js +0 -387
  108. package/dist/chunk-ADIAWL34.js +0 -81
  109. package/dist/chunk-ASTEMBKJ.js +0 -519
  110. package/dist/chunk-CEMMLV5L.js +0 -98
  111. package/dist/chunk-CM5HNV2W.js +0 -131
  112. package/dist/chunk-CRTRBBRI.js +0 -105
  113. package/dist/chunk-DA2KGZZI.js +0 -13
  114. package/dist/chunk-DIB4GX3G.js +0 -8
  115. package/dist/chunk-DKIJ2RP5.js +0 -68
  116. package/dist/chunk-DWPN6SCH.js +0 -172
  117. package/dist/chunk-EDKUFGPL.js +0 -64
  118. package/dist/chunk-ENY6SKIU.js +0 -1228
  119. package/dist/chunk-F4MGCZOX.js +0 -2943
  120. package/dist/chunk-FA6POGLH.js +0 -70
  121. package/dist/chunk-FSUR7GTG.js +0 -20475
  122. package/dist/chunk-GKEOHJL5.js +0 -1856
  123. package/dist/chunk-GMCB6W5Y.js +0 -333
  124. package/dist/chunk-IE2VPG7O.js +0 -1135
  125. package/dist/chunk-IZ5B5IHQ.js +0 -3656
  126. package/dist/chunk-JAL3CH4G.js +0 -27
  127. package/dist/chunk-KIIEUXD3.js +0 -1764
  128. package/dist/chunk-KXU4NIL7.js +0 -692
  129. package/dist/chunk-MTM5IFCY.js +0 -1190
  130. package/dist/chunk-N7TMSOZH.js +0 -235
  131. package/dist/chunk-NCEBK6PH.js +0 -36
  132. package/dist/chunk-NHJU2ZAL.js +0 -56
  133. package/dist/chunk-P6KTRNVC.js +0 -321
  134. package/dist/chunk-PDO5BLNM.js +0 -22
  135. package/dist/chunk-PDRNLLFT.js +0 -3295
  136. package/dist/chunk-PEQXYSSE.js +0 -45
  137. package/dist/chunk-PKEX2AQX.js +0 -198
  138. package/dist/chunk-PSJCGIGO.js +0 -1163
  139. package/dist/chunk-PZUSUL55.js +0 -506
  140. package/dist/chunk-R45M4TUS.js +0 -37
  141. package/dist/chunk-RC745GGZ.js +0 -122
  142. package/dist/chunk-SP3QKZXJ.js +0 -820
  143. package/dist/chunk-TXKUKMVO.js +0 -417
  144. package/dist/chunk-UE4GPWSD.js +0 -931
  145. package/dist/chunk-UIE3R5XU.js +0 -17
  146. package/dist/chunk-UXPG6ZIN.js +0 -84
  147. package/dist/chunk-VFUK3X5B.js +0 -50
  148. package/dist/chunk-VNMJWREK.js +0 -787
  149. package/dist/chunk-VZ7CSOX2.js +0 -706
  150. package/dist/chunk-WCNQJKFT.js +0 -10
  151. package/dist/chunk-WDZR3QQM.js +0 -135
  152. package/dist/chunk-WLYVJCHV.js +0 -1433
  153. package/dist/chunk-WS7NAFTM.js +0 -1520
  154. package/dist/chunk-X6GDDWQH.js +0 -60
  155. package/dist/chunk-XPDEYNQI.js +0 -102
  156. package/dist/chunk-XRW44VGM.js +0 -58
  157. package/dist/chunk-Y2CM7HXH.js +0 -111
  158. package/dist/chunk-Y7X25LFY.js +0 -15
  159. package/dist/conversation-work-VIOQ5ZF3.js +0 -54
  160. package/dist/db-NGDJV7YH.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-YFY7YEGK.js +0 -243
  164. package/dist/oauth-relay-5XPVRPYB.js +0 -8
  165. package/dist/plugins-YTYJMMJF.js +0 -14
  166. package/dist/runner-ORTNSB2Q.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-H376WQOH.js +0 -27
  170. package/dist/spawn-T43WHLOS.js +0 -42
  171. package/dist/task-runner-LBZWF32V.js +0 -36
  172. package/dist/validation-REJLRKI6.js +0 -17
  173. package/dist/work-3KJ3RE76.js +0 -51
  174. package/dist/worker-QFEBU72E.js +0 -24
@@ -0,0 +1,296 @@
1
+ import { n as botConfig } from "./config-nGCW1OTG.js";
2
+ import { f as logWarn } from "./logging-BzAk1S_s.js";
3
+ import { t as usageSchema } from "./usage-schema-CKaDkH_j.js";
4
+ import { z } from "zod";
5
+ import { conversationEventPresentationSchema, defineConversationEvent } from "@sentry/junior-plugin-api";
6
+ //#region src/chat/conversations/structured-events.ts
7
+ /** Reserved namespace for Junior-owned conversation metadata events. */
8
+ const JUNIOR_NATIVE_EVENT_NAMESPACE = "junior";
9
+ const authenticationEventContentSchema = z.object({
10
+ accountLabel: z.string().trim().min(1).max(120).optional(),
11
+ actorId: z.string().min(1),
12
+ authorizationId: z.string().min(1).optional(),
13
+ provider: z.string().regex(/^[a-z][a-z0-9-]*$/),
14
+ providerLabel: z.string().trim().min(1).max(80).optional()
15
+ }).strict();
16
+ const agentsInstructionsUpdatedContentSchema = z.object({
17
+ action: z.enum([
18
+ "loaded",
19
+ "replaced",
20
+ "cleared"
21
+ ]),
22
+ directory: z.string().trim().min(1).max(500).optional(),
23
+ fingerprint: z.string().trim().min(1).max(128),
24
+ sources: z.array(z.object({
25
+ content: z.string().min(1).max(32768),
26
+ path: z.string().trim().min(1).max(500)
27
+ }).strict()).max(32),
28
+ textBytes: z.number().int().nonnegative().optional()
29
+ }).strict();
30
+ function providerTitle(content) {
31
+ return content.providerLabel?.trim() || content.provider;
32
+ }
33
+ function agentsInstructionsTitle(action) {
34
+ if (action === "loaded") return "Loaded AGENTS.md";
35
+ if (action === "replaced") return "Updated AGENTS.md";
36
+ return "Cleared AGENTS.md";
37
+ }
38
+ function sourceFilename(sourcePath) {
39
+ return sourcePath.split("/").at(-1) || sourcePath;
40
+ }
41
+ function formatBytes(bytes) {
42
+ if (bytes < 1024) return `${bytes} bytes`;
43
+ const kilobytes = bytes / 1024;
44
+ return `${Number.isInteger(kilobytes) ? kilobytes : kilobytes.toFixed(1)} KB`;
45
+ }
46
+ function agentsInstructionsPreview(content) {
47
+ const source = content.sources[0];
48
+ if (!source) return void 0;
49
+ const filename = sourceFilename(source.path);
50
+ const label = content.sources.length === 1 ? filename : `${content.sources.length} AGENTS.md files`;
51
+ return typeof content.textBytes === "number" ? `${label} · ${formatBytes(content.textBytes)}` : label;
52
+ }
53
+ /** Junior-owned account-link transcript event. */
54
+ const authenticationLinkedEvent = defineConversationEvent({
55
+ name: "authentication_linked",
56
+ version: 1,
57
+ schema: authenticationEventContentSchema,
58
+ renderEvent(event) {
59
+ const provider = providerTitle(event);
60
+ return {
61
+ icon: "link",
62
+ title: `${provider} connected`,
63
+ ...event.accountLabel ? { preview: `Connected as \`${event.accountLabel}\`` } : void 0,
64
+ details: [{
65
+ title: `${provider} connected`,
66
+ ...event.accountLabel ? { description: `Connected as \`${event.accountLabel}\`` } : void 0,
67
+ metadata: [event.provider]
68
+ }]
69
+ };
70
+ }
71
+ });
72
+ /** Junior-owned account-unlink transcript event. */
73
+ const authenticationUnlinkedEvent = defineConversationEvent({
74
+ name: "authentication_unlinked",
75
+ version: 1,
76
+ schema: authenticationEventContentSchema,
77
+ renderEvent(event) {
78
+ const provider = providerTitle(event);
79
+ return {
80
+ icon: "key",
81
+ title: `${provider} disconnected`,
82
+ details: [{
83
+ title: `${provider} disconnected`,
84
+ metadata: [event.provider]
85
+ }]
86
+ };
87
+ }
88
+ });
89
+ /** Junior-owned AGENTS.md bootstrap transition for the dashboard timeline. */
90
+ const agentsInstructionsUpdatedEvent = defineConversationEvent({
91
+ name: "agents_instructions_updated",
92
+ version: 1,
93
+ schema: agentsInstructionsUpdatedContentSchema,
94
+ renderEvent(event) {
95
+ const title = agentsInstructionsTitle(event.action);
96
+ const preview = agentsInstructionsPreview(event);
97
+ return {
98
+ icon: "brain",
99
+ title,
100
+ ...preview ? { preview } : void 0,
101
+ ...event.sources.length > 0 ? { details: event.sources.map((source) => ({
102
+ title: sourceFilename(source.path),
103
+ content: source.content
104
+ })) } : void 0
105
+ };
106
+ }
107
+ });
108
+ const NATIVE_EVENT_DEFINITIONS = [
109
+ authenticationLinkedEvent,
110
+ authenticationUnlinkedEvent,
111
+ agentsInstructionsUpdatedEvent
112
+ ];
113
+ /** Resolve a registered Junior-native conversation event definition. */
114
+ function getJuniorNativeEventDefinition(args) {
115
+ return NATIVE_EVENT_DEFINITIONS.find((definition) => definition.eventName === args.name && definition.version === args.version);
116
+ }
117
+ /** Render one Junior-native event through its active definition. */
118
+ function renderJuniorNativeConversationEvent(args) {
119
+ if (args.namespace !== "junior") return void 0;
120
+ const definition = getJuniorNativeEventDefinition(args);
121
+ if (!definition) return void 0;
122
+ const presentation = definition.renderEvent(definition.parse(args.content));
123
+ return presentation === void 0 ? void 0 : conversationEventPresentationSchema.parse(presentation);
124
+ }
125
+ const TITLE_PROMPTS = {
126
+ conversation: [
127
+ "Generate a concise 5-8 word conversation title from the first user message below.",
128
+ "Capture the user's main request.",
129
+ "Reply with ONLY the title, with no quotes or trailing punctuation."
130
+ ],
131
+ task: [
132
+ "Generate a concise 5-8 word task title from the task instruction below.",
133
+ "Capture the task's main purpose.",
134
+ "Reply with ONLY the title, with no quotes or trailing punctuation."
135
+ ]
136
+ };
137
+ /** Collapse whitespace and cap a candidate short title. */
138
+ function normalizeShortTitle(value) {
139
+ return value.replace(/\s+/g, " ").trim().slice(0, 60);
140
+ }
141
+ /**
142
+ * Deterministic display title when no generated title is stored.
143
+ * Uses the first non-empty line of the source text, capped like generated titles.
144
+ */
145
+ function fallbackShortTitle(sourceText, fallback = "Untitled") {
146
+ return normalizeShortTitle(sourceText.split(/\r?\n/).map((line) => line.trim()).find((line) => line.length > 0) ?? "") || fallback;
147
+ }
148
+ /** Generate a short title with the fast model, or return undefined on failure. */
149
+ async function generateShortTitle(args) {
150
+ const sourceText = args.sourceText.trim();
151
+ if (!sourceText) return void 0;
152
+ try {
153
+ return normalizeShortTitle((await args.completeText({
154
+ modelId: botConfig.fastModelId,
155
+ temperature: 0,
156
+ promptName: `junior.${args.kind}_title`,
157
+ messages: [{
158
+ role: "user",
159
+ content: [
160
+ ...TITLE_PROMPTS[args.kind],
161
+ "",
162
+ args.kind === "conversation" ? `First user message: ${sourceText.slice(0, 500)}` : `Task instruction: ${sourceText.slice(0, 500)}`
163
+ ].join("\n"),
164
+ timestamp: Date.now()
165
+ }],
166
+ metadata: { modelId: botConfig.fastModelId }
167
+ })).text) || void 0;
168
+ } catch (error) {
169
+ logWarn(`${args.kind}.title.generation.failed`, { "exception.message": error instanceof Error ? error.message : String(error) });
170
+ return;
171
+ }
172
+ }
173
+ /**
174
+ * Prefer an explicit task title when provided; otherwise generate one from the
175
+ * instruction with the fast model.
176
+ */
177
+ async function resolveTaskTitle(args) {
178
+ const explicit = normalizeShortTitle(args.title ?? "");
179
+ if (explicit) return explicit;
180
+ return generateShortTitle({
181
+ completeText: args.completeText,
182
+ kind: "task",
183
+ sourceText: args.instruction
184
+ });
185
+ }
186
+ //#endregion
187
+ //#region src/chat/tools/execution/tool-input-error.ts
188
+ /** Thrown when a tool fails due to invalid model/user input, not a system error. */
189
+ var ToolInputError = class extends Error {
190
+ constructor(message, options) {
191
+ super(message, options);
192
+ this.name = "ToolInputError";
193
+ }
194
+ };
195
+ //#endregion
196
+ //#region src/chat/usage.ts
197
+ const agentTurnUsageSchema = usageSchema;
198
+ const COMPONENT_USAGE_FIELDS = [
199
+ "inputTokens",
200
+ "outputTokens",
201
+ "cachedInputTokens",
202
+ "cacheCreationTokens"
203
+ ];
204
+ const COST_COMPONENT_FIELDS = [
205
+ "input",
206
+ "output",
207
+ "cacheRead",
208
+ "cacheWrite"
209
+ ];
210
+ /** Return whether any token counter is present on a usage record. */
211
+ function hasAgentTurnUsage(usage) {
212
+ return Boolean(usage && (Object.entries(usage).some(([field, value]) => field !== "cost" && typeof value === "number" && Number.isFinite(value)) || Object.values(usage.cost ?? {}).some((value) => typeof value === "number" && Number.isFinite(value))));
213
+ }
214
+ function getFiniteCount(value) {
215
+ return typeof value === "number" && Number.isFinite(value) ? Math.max(0, Math.floor(value)) : void 0;
216
+ }
217
+ function getFiniteCost(value) {
218
+ return typeof value === "number" && Number.isFinite(value) ? Math.max(0, value) : void 0;
219
+ }
220
+ function addCost(left, right) {
221
+ return Math.round(((left ?? 0) + right) * 0xe8d4a51000) / 0xe8d4a51000;
222
+ }
223
+ function getComponentTotal(usage) {
224
+ let total;
225
+ for (const field of COMPONENT_USAGE_FIELDS) {
226
+ const value = getFiniteCount(usage[field]);
227
+ if (value === void 0) continue;
228
+ total = (total ?? 0) + value;
229
+ }
230
+ return total;
231
+ }
232
+ /** Estimated total USD cost from one usage record, when any cost field is present. */
233
+ function agentTurnCostUsd(usage) {
234
+ if (!usage?.cost) return void 0;
235
+ const total = getFiniteCost(usage.cost.total);
236
+ if (total !== void 0) return total;
237
+ let componentTotal = 0;
238
+ let hasComponent = false;
239
+ for (const field of COST_COMPONENT_FIELDS) {
240
+ const value = getFiniteCost(usage.cost[field]);
241
+ if (value === void 0) continue;
242
+ hasComponent = true;
243
+ componentTotal = addCost(componentTotal, value);
244
+ }
245
+ return hasComponent ? componentTotal : void 0;
246
+ }
247
+ /** Total token count from one usage record, preferring component counters. */
248
+ function agentTurnTotalTokens(usage) {
249
+ if (!usage) return void 0;
250
+ const componentTotal = getComponentTotal(usage);
251
+ if (componentTotal !== void 0) return componentTotal;
252
+ return getFiniteCount(usage.totalTokens);
253
+ }
254
+ /** Aggregate token usage across slices without double-counting provider totals. */
255
+ function addAgentTurnUsage(...usages) {
256
+ const components = {};
257
+ let componentTotal;
258
+ let totalOnlyTokens;
259
+ let reasoningTokens;
260
+ const cost = {};
261
+ for (const usage of usages) {
262
+ if (!usage) continue;
263
+ const reasoning = getFiniteCount(usage.reasoningTokens);
264
+ if (reasoning !== void 0) reasoningTokens = (reasoningTokens ?? 0) + reasoning;
265
+ if (usage.cost) for (const field of [...COST_COMPONENT_FIELDS, "total"]) {
266
+ const value = getFiniteCost(usage.cost[field]);
267
+ if (value === void 0) continue;
268
+ cost[field] = addCost(cost[field], value);
269
+ }
270
+ const usageComponentTotal = getComponentTotal(usage);
271
+ if (usageComponentTotal !== void 0) {
272
+ componentTotal = (componentTotal ?? 0) + usageComponentTotal;
273
+ for (const field of COMPONENT_USAGE_FIELDS) {
274
+ const value = getFiniteCount(usage[field]);
275
+ if (value === void 0) continue;
276
+ components[field] = (components[field] ?? 0) + value;
277
+ }
278
+ continue;
279
+ }
280
+ const totalTokens = getFiniteCount(usage.totalTokens);
281
+ if (totalTokens !== void 0) totalOnlyTokens = (totalOnlyTokens ?? 0) + totalTokens;
282
+ }
283
+ if (totalOnlyTokens !== void 0) return {
284
+ totalTokens: totalOnlyTokens + (componentTotal ?? 0),
285
+ ...reasoningTokens !== void 0 ? { reasoningTokens } : void 0,
286
+ ...Object.keys(cost).length > 0 ? { cost } : void 0
287
+ };
288
+ const result = {
289
+ ...components,
290
+ ...reasoningTokens !== void 0 ? { reasoningTokens } : void 0,
291
+ ...Object.keys(cost).length > 0 ? { cost } : void 0
292
+ };
293
+ return hasAgentTurnUsage(result) ? result : void 0;
294
+ }
295
+ //#endregion
296
+ export { hasAgentTurnUsage as a, generateShortTitle as c, agentsInstructionsUpdatedEvent as d, authenticationLinkedEvent as f, agentTurnUsageSchema as i, resolveTaskTitle as l, renderJuniorNativeConversationEvent as m, agentTurnCostUsd as n, ToolInputError as o, authenticationUnlinkedEvent as p, agentTurnTotalTokens as r, fallbackShortTitle as s, addAgentTurnUsage as t, JUNIOR_NATIVE_EVENT_NAMESPACE as u };
@@ -0,0 +1,20 @@
1
+ import { z } from "zod";
2
+ //#region src/usage-schema.ts
3
+ const usageCostSchema = z.object({
4
+ input: z.number().finite().nonnegative().optional(),
5
+ output: z.number().finite().nonnegative().optional(),
6
+ cacheRead: z.number().finite().nonnegative().optional(),
7
+ cacheWrite: z.number().finite().nonnegative().optional(),
8
+ total: z.number().finite().nonnegative().optional()
9
+ }).strict();
10
+ const usageSchema = z.object({
11
+ inputTokens: z.number().int().nonnegative().optional(),
12
+ outputTokens: z.number().int().nonnegative().optional(),
13
+ cachedInputTokens: z.number().int().nonnegative().optional(),
14
+ cacheCreationTokens: z.number().int().nonnegative().optional(),
15
+ reasoningTokens: z.number().int().nonnegative().optional(),
16
+ totalTokens: z.number().int().nonnegative().optional(),
17
+ cost: usageCostSchema.optional()
18
+ }).strict();
19
+ //#endregion
20
+ export { usageSchema as t };
@@ -0,0 +1,40 @@
1
+ import { t as __exportAll } from "./rolldown-runtime-B4FMCO8f.js";
2
+ import { n as pluginCatalogRuntime } from "./catalog-runtime-BReos-D4.js";
3
+ import { isDeepStrictEqual } from "node:util";
4
+ //#region src/chat/plugins/validation.ts
5
+ var validation_exports = /* @__PURE__ */ __exportAll({
6
+ validatePluginEgressCredentialHooks: () => validatePluginEgressCredentialHooks,
7
+ validatePluginRegistrations: () => validatePluginRegistrations
8
+ });
9
+ /** Validate hook registrations against the loaded plugin manifest catalog. */
10
+ function validatePluginRegistrations(registrations) {
11
+ const loadedPlugins = new Map(pluginCatalogRuntime.getProviders().map((plugin) => [plugin.manifest.name, plugin]));
12
+ for (const registration of registrations) {
13
+ const loadedPlugin = loadedPlugins.get(registration.manifest.name);
14
+ if (!loadedPlugin) throw new Error(`Plugin registration "${registration.manifest.name}" does not have a matching plugin manifest. Add an inline manifest, packageName, or app-local plugin.yaml with the same name.`);
15
+ const effectiveRegistrationManifest = pluginCatalogRuntime.parseConfiguredInlineManifest(registration.manifest, loadedPlugin.dir);
16
+ if (!isDeepStrictEqual(effectiveRegistrationManifest, loadedPlugin.manifest)) throw new Error(`Plugin registration "${registration.manifest.name}" manifest does not match the loaded plugin manifest. Use one canonical manifest source for runtime hook plugins.`);
17
+ }
18
+ }
19
+ /** Validate credential hook registrations against the loaded plugin manifests. */
20
+ function validatePluginEgressCredentialHooks(registrations) {
21
+ const plugins = new Map(registrations.map((registration) => [registration.manifest.name, registration]));
22
+ for (const provider of pluginCatalogRuntime.getProviders()) {
23
+ const hooks = plugins.get(provider.manifest.name)?.hooks;
24
+ const hasGrantHook = Boolean(hooks?.grantForEgress);
25
+ const hasIssueHook = Boolean(hooks?.issueCredential);
26
+ const hasGenericCredentials = Boolean(provider.manifest.credentials || provider.manifest.apiHeaders);
27
+ const hasDomains = Boolean(provider.manifest.domains?.length);
28
+ const hasHookManagedOAuth = Boolean(provider.manifest.oauth && !provider.manifest.credentials);
29
+ if (!hasGrantHook && !hasIssueHook) {
30
+ if (hasDomains && !hasGenericCredentials) throw new Error(`Plugin "${provider.manifest.name}" manifest.domains requires egress credential hooks when no generic credentials or apiHeaders are configured.`);
31
+ if (hasHookManagedOAuth) throw new Error(`Plugin "${provider.manifest.name}" manifest.oauth without oauth-bearer credentials requires egress credential hooks.`);
32
+ continue;
33
+ }
34
+ if (!hasGrantHook || !hasIssueHook) throw new Error(`Plugin "${provider.manifest.name}" egress credential hooks must include both grantForEgress and issueCredential.`);
35
+ if (hasGenericCredentials) throw new Error(`Plugin "${provider.manifest.name}" egress credential hooks must use manifest.domains instead of generic credentials or apiHeaders.`);
36
+ if (!hasDomains) throw new Error(`Plugin "${provider.manifest.name}" egress credential hooks require manifest.domains to list sandbox egress hosts.`);
37
+ }
38
+ }
39
+ //#endregion
40
+ export { validatePluginRegistrations as n, validation_exports as r, validatePluginEgressCredentialHooks as t };
@@ -0,0 +1,167 @@
1
+ import { z } from "zod";
2
+ import { createHmac, timingSafeEqual } from "node:crypto";
3
+ import { QueueClient } from "@vercel/queue";
4
+ /** Validate the v2 conversation work hint sent through Vercel Queue. */
5
+ const conversationQueueMessageSchema = z.object({
6
+ schemaVersion: z.literal(2),
7
+ conversationId: z.string().trim().min(1)
8
+ }).strict();
9
+ var ConversationQueueMessageRejectedError = class extends Error {
10
+ conversationId;
11
+ reason;
12
+ constructor(reason, message, options = {}) {
13
+ super(message);
14
+ this.name = "ConversationQueueMessageRejectedError";
15
+ this.reason = reason;
16
+ this.conversationId = options.conversationId;
17
+ }
18
+ };
19
+ /** Return whether an error means the queue message was permanently rejected. */
20
+ function isConversationQueueMessageRejectedError(error) {
21
+ return error instanceof ConversationQueueMessageRejectedError;
22
+ }
23
+ //#endregion
24
+ //#region src/chat/vercel-queue-client.ts
25
+ function defaultQueueClientOptions() {
26
+ if (process.env.VERCEL_DEPLOYMENT_ID?.trim()) return {};
27
+ return { deploymentId: null };
28
+ }
29
+ /** Create a Vercel Queue client that also works in local and eval runtimes. */
30
+ function createVercelQueueClient() {
31
+ return new QueueClient(defaultQueueClientOptions());
32
+ }
33
+ //#endregion
34
+ //#region src/chat/queue/sign.ts
35
+ /** Sign and check queue messages before public callbacks run them. */
36
+ const QUEUE_SIGNATURE_MAX_AGE_MS = 36e5;
37
+ function secret() {
38
+ return process.env.JUNIOR_SECRET?.trim() || void 0;
39
+ }
40
+ function digest(args) {
41
+ return createHmac("sha256", args.secret).update([
42
+ args.context,
43
+ args.signedAtMs,
44
+ ...args.parts
45
+ ].join(args.separator)).digest("hex");
46
+ }
47
+ function sameHex(expected, actual) {
48
+ const left = Buffer.from(expected);
49
+ const right = Buffer.from(actual);
50
+ return left.length === right.length && timingSafeEqual(left, right);
51
+ }
52
+ function body(value) {
53
+ const { signature: _signature, signatureVersion: _signatureVersion, signedAtMs: _signedAtMs, ...message } = value;
54
+ return message;
55
+ }
56
+ /** Sign one queue message. */
57
+ function signQueueMessage(config, message, nowMs = Date.now()) {
58
+ const key = secret();
59
+ if (!key) throw new Error("Cannot sign queue message without JUNIOR_SECRET");
60
+ if (!Number.isFinite(nowMs)) throw new Error("Cannot sign queue message with an invalid clock");
61
+ const separator = config.separator ?? "\0";
62
+ return {
63
+ ...message,
64
+ signedAtMs: nowMs,
65
+ signatureVersion: config.signatureVersion,
66
+ signature: digest({
67
+ context: config.context,
68
+ parts: config.parts(message),
69
+ secret: key,
70
+ separator,
71
+ signedAtMs: nowMs
72
+ })
73
+ };
74
+ }
75
+ /** Check one signed queue message. */
76
+ function verifyQueueMessage(config, value, nowMs = Date.now()) {
77
+ if (!value || typeof value !== "object" || Array.isArray(value)) return {
78
+ status: "rejected",
79
+ reason: "malformed"
80
+ };
81
+ const signed = z.object({
82
+ signature: z.string().trim().min(1),
83
+ signatureVersion: z.literal(config.signatureVersion),
84
+ signedAtMs: z.number().finite()
85
+ }).safeParse(value);
86
+ const message = config.schema.safeParse(body(value));
87
+ if (!signed.success || !message.success) return {
88
+ status: "rejected",
89
+ reason: "malformed"
90
+ };
91
+ const key = secret();
92
+ if (!key) return {
93
+ status: "unavailable",
94
+ reason: "missing_secret"
95
+ };
96
+ if (!Number.isFinite(nowMs)) return {
97
+ status: "unavailable",
98
+ reason: "invalid_clock"
99
+ };
100
+ const maxAgeMs = config.maxAgeMs ?? 36e5;
101
+ if (Math.abs(nowMs - signed.data.signedAtMs) > maxAgeMs) return {
102
+ status: "rejected",
103
+ reason: "expired"
104
+ };
105
+ if (!sameHex(digest({
106
+ context: config.context,
107
+ parts: config.parts(message.data),
108
+ secret: key,
109
+ separator: config.separator ?? "\0",
110
+ signedAtMs: signed.data.signedAtMs
111
+ }), signed.data.signature)) return {
112
+ status: "rejected",
113
+ reason: "signature_mismatch"
114
+ };
115
+ return {
116
+ status: "verified",
117
+ message: message.data
118
+ };
119
+ }
120
+ //#endregion
121
+ //#region src/chat/task-execution/queue-signing.ts
122
+ const conversationQueueSign = {
123
+ context: "junior.conversation_work_queue.v2",
124
+ schema: conversationQueueMessageSchema,
125
+ separator: ":",
126
+ signatureVersion: "v2",
127
+ parts: (message) => [message.conversationId]
128
+ };
129
+ const CONVERSATION_WORK_QUEUE_SIGNATURE_MAX_SKEW_MS = QUEUE_SIGNATURE_MAX_AGE_MS;
130
+ /** Sign a conversation queue payload before it crosses the public callback route. */
131
+ function signConversationQueueMessage(message, nowMs = Date.now()) {
132
+ return signQueueMessage(conversationQueueSign, message, nowMs);
133
+ }
134
+ /** Explain whether a queue payload is verified, rejected, or unavailable. */
135
+ function verifyConversationQueueMessage(value, nowMs = Date.now()) {
136
+ return verifyQueueMessage(conversationQueueSign, value, nowMs);
137
+ }
138
+ const CONVERSATION_WORK_QUEUE_RETENTION_SECONDS = CONVERSATION_WORK_QUEUE_SIGNATURE_MAX_SKEW_MS / 1e3;
139
+ let defaultQueue;
140
+ /** Resolve the Vercel Queue topic used for conversation wake-up nudges. */
141
+ function resolveConversationWorkQueueTopic(options = {}) {
142
+ return options.topic?.trim() || process.env.JUNIOR_CONVERSATION_WORK_QUEUE_TOPIC?.trim() || "junior_conversation_work";
143
+ }
144
+ function toDelaySeconds(options) {
145
+ if (!options?.delayMs || options.delayMs <= 0) return;
146
+ return Math.ceil(options.delayMs / 1e3);
147
+ }
148
+ /** Create the Vercel Queue implementation for conversation wake-up nudges. */
149
+ function createVercelConversationWorkQueue(options = {}) {
150
+ const topic = resolveConversationWorkQueueTopic(options);
151
+ const client = options.client ?? createVercelQueueClient();
152
+ return { async send(message, sendOptions) {
153
+ const result = await client.send(topic, signConversationQueueMessage(message), {
154
+ idempotencyKey: sendOptions?.idempotencyKey,
155
+ delaySeconds: toDelaySeconds(sendOptions),
156
+ retentionSeconds: options.retentionSeconds ?? CONVERSATION_WORK_QUEUE_RETENTION_SECONDS
157
+ });
158
+ return result.messageId ? { messageId: result.messageId } : {};
159
+ } };
160
+ }
161
+ /** Return the default production conversation work queue. */
162
+ function getVercelConversationWorkQueue() {
163
+ defaultQueue ??= createVercelConversationWorkQueue();
164
+ return defaultQueue;
165
+ }
166
+ //#endregion
167
+ export { signQueueMessage as a, ConversationQueueMessageRejectedError as c, QUEUE_SIGNATURE_MAX_AGE_MS as i, conversationQueueMessageSchema as l, resolveConversationWorkQueueTopic as n, verifyQueueMessage as o, verifyConversationQueueMessage as r, createVercelQueueClient as s, getVercelConversationWorkQueue as t, isConversationQueueMessageRejectedError as u };
package/dist/vercel.d.ts CHANGED
@@ -1,12 +1,12 @@
1
- interface JuniorVercelConfigOptions {
2
- /** Override the Vercel build command, or pass null to omit it. */
3
- buildCommand?: string | null;
1
+ //#region src/vercel.d.ts
2
+ export interface JuniorVercelConfigOptions {
3
+ /** Override the Vercel build command, or pass null to omit it. */
4
+ buildCommand?: string | null;
4
5
  }
5
6
  /** Return the root Vercel project config for scaffolded Junior apps.
6
7
  *
7
8
  * New apps run `junior upgrade` before `pnpm build`; older installs without
8
9
  * Junior SQL configured can override `buildCommand` to keep their prior build.
9
10
  */
10
- declare function juniorVercelConfig(options?: JuniorVercelConfigOptions): Record<string, unknown>;
11
-
12
- export { type JuniorVercelConfigOptions, juniorVercelConfig };
11
+ export declare function juniorVercelConfig(options?: JuniorVercelConfigOptions): Record<string, unknown>;
12
+ //#endregion
package/dist/vercel.js CHANGED
@@ -1,6 +1,14 @@
1
- import {
2
- juniorVercelConfig
3
- } from "./chunk-Y7X25LFY.js";
4
- export {
5
- juniorVercelConfig
6
- };
1
+ //#region src/vercel.ts
2
+ /** Return the root Vercel project config for scaffolded Junior apps.
3
+ *
4
+ * New apps run `junior upgrade` before `pnpm build`; older installs without
5
+ * Junior SQL configured can override `buildCommand` to keep their prior build.
6
+ */
7
+ function juniorVercelConfig(options = {}) {
8
+ const buildCommand = options.buildCommand === void 0 ? "pnpm exec junior upgrade && pnpm build" : options.buildCommand;
9
+ const config = { framework: "nitro" };
10
+ if (buildCommand !== null) config.buildCommand = buildCommand;
11
+ return config;
12
+ }
13
+ //#endregion
14
+ export { juniorVercelConfig };
@@ -0,0 +1,5 @@
1
+ //#region src/version.d.ts
2
+ /** Installed Junior package version, or `unknown` when package metadata is unavailable. */
3
+ declare const JUNIOR_VERSION: string;
4
+ //#endregion
5
+ export { JUNIOR_VERSION as t };
@@ -0,0 +1,8 @@
1
+ //#region package.json
2
+ var version = "0.204.0";
3
+ //#endregion
4
+ //#region src/version.ts
5
+ /** Installed Junior package version, or `unknown` when package metadata is unavailable. */
6
+ const JUNIOR_VERSION = typeof version === "string" && version.trim() ? version : "unknown";
7
+ //#endregion
8
+ export { JUNIOR_VERSION as t };
package/dist/version.d.ts CHANGED
@@ -1,4 +1,2 @@
1
- /** Installed Junior package version, or `unknown` when package metadata is unavailable. */
2
- declare const JUNIOR_VERSION: string;
3
-
4
- export { JUNIOR_VERSION };
1
+ import { t as JUNIOR_VERSION } from "./version-CnXZ614E.js";
2
+ export { JUNIOR_VERSION };
package/dist/version.js CHANGED
@@ -1,6 +1,2 @@
1
- import {
2
- JUNIOR_VERSION
3
- } from "./chunk-WDZR3QQM.js";
4
- export {
5
- JUNIOR_VERSION
6
- };
1
+ import { t as JUNIOR_VERSION } from "./version-DxcWdoKa.js";
2
+ export { JUNIOR_VERSION };
@@ -0,0 +1,76 @@
1
+ import { a as getClient } from "./sentry-CD3SdJl-.js";
2
+ import { w as getStateAdapter } from "./profile-CrT5nXbw.js";
3
+ import { randomUUID } from "node:crypto";
4
+ //#region src/chat/sentry-links.ts
5
+ function getSentryOrgSlug() {
6
+ return process.env.SENTRY_ORG_SLUG?.trim() || void 0;
7
+ }
8
+ function isSentrySaasDsnHost(host) {
9
+ return host === "sentry.io" || host.endsWith(".sentry.io");
10
+ }
11
+ function buildSentryWebBaseUrl(dsn) {
12
+ if (isSentrySaasDsnHost(dsn.host)) return "https://sentry.io";
13
+ const port = dsn.port ? `:${dsn.port}` : "";
14
+ const path = dsn.path ? `/${dsn.path}` : "";
15
+ return `${dsn.protocol}://${dsn.host}${port}${path}`;
16
+ }
17
+ function buildSentryOrgPath(args) {
18
+ const dsn = getClient()?.getDsn();
19
+ if (!dsn?.host || !dsn.projectId) return;
20
+ const orgSlug = getSentryOrgSlug();
21
+ if (!orgSlug) return;
22
+ const params = new URLSearchParams();
23
+ params.set("project", dsn.projectId);
24
+ if (args.query) for (const [key, value] of Object.entries(args.query)) params.set(key, value);
25
+ const path = `${args.path}?${params.toString()}`;
26
+ if (isSentrySaasDsnHost(dsn.host)) return `https://${orgSlug}.sentry.io/${path}`;
27
+ return `${buildSentryWebBaseUrl(dsn)}/organizations/${orgSlug}/${path}`;
28
+ }
29
+ /** Build a Sentry conversation URL only when the runtime has enough Sentry config. */
30
+ function buildSentryConversationUrl(conversationId) {
31
+ return buildSentryOrgPath({ path: `explore/conversations/${encodeURIComponent(conversationId)}/` });
32
+ }
33
+ /** Build a Sentry event URL only when the runtime has enough Sentry config. */
34
+ function buildSentryEventUrl(eventId) {
35
+ return buildSentryOrgPath({
36
+ path: "issues/",
37
+ query: { query: eventId }
38
+ });
39
+ }
40
+ //#endregion
41
+ //#region src/chat/conversations/web-authorization.ts
42
+ const WEB_AUTHORIZATION_PREFIX = "junior:web_authorization:v1";
43
+ const WEB_AUTHORIZATION_TTL_MS = 864e5;
44
+ function authorizationKey(conversationId, actorId) {
45
+ return `${WEB_AUTHORIZATION_PREFIX}:${conversationId}:${actorId}`;
46
+ }
47
+ /** Build authorization delivery for one web turn. */
48
+ function createWebAuthorization(args) {
49
+ return {
50
+ createState: async () => randomUUID(),
51
+ deliver: async (request) => {
52
+ await getStateAdapter().set(authorizationKey(args.conversationId, args.actorId), JSON.stringify({
53
+ ...request,
54
+ ...args
55
+ }), WEB_AUTHORIZATION_TTL_MS);
56
+ }
57
+ };
58
+ }
59
+ /** Read the pending authorization request for one web actor. */
60
+ async function getWebAuthorization(args) {
61
+ const value = await getStateAdapter().get(authorizationKey(args.conversationId, args.actorId));
62
+ if (typeof value !== "string") return void 0;
63
+ try {
64
+ const parsed = JSON.parse(value);
65
+ if (parsed.actorId !== args.actorId || parsed.conversationId !== args.conversationId || typeof parsed.authorizationUrl !== "string" || typeof parsed.label !== "string" || typeof parsed.completionText !== "string") return;
66
+ return parsed;
67
+ } catch {
68
+ return;
69
+ }
70
+ }
71
+ /** Remove a web authorization request after the parked turn continues. */
72
+ async function deleteWebAuthorization(args) {
73
+ await getStateAdapter().delete(authorizationKey(args.conversationId, args.actorId));
74
+ }
75
+ //#endregion
76
+ export { buildSentryEventUrl as a, buildSentryConversationUrl as i, deleteWebAuthorization as n, getWebAuthorization as r, createWebAuthorization as t };