@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
@@ -1,706 +0,0 @@
1
- import {
2
- SANDBOX_WORKSPACE_ROOT,
3
- create,
4
- getVercelSandboxCredentials,
5
- isSandboxUnavailableError,
6
- isStale,
7
- runNonInteractiveCommand,
8
- sleep
9
- } from "./chunk-NSXKRGRT.js";
10
- import {
11
- getStateAdapter
12
- } from "./chunk-2MK3QBGA.js";
13
- import {
14
- setSpanAttributes,
15
- withSpan
16
- } from "./chunk-MAGNK5J4.js";
17
-
18
- // src/chat/sandbox/resources.ts
19
- var configuredResources;
20
- function resourcesFromEnv() {
21
- const value = process.env.SANDBOX_VCPUS?.trim();
22
- if (!value || !/^\d+$/.test(value)) {
23
- return void 0;
24
- }
25
- const vcpus = Number(value);
26
- if (!Number.isSafeInteger(vcpus) || vcpus <= 0) {
27
- return void 0;
28
- }
29
- return { vcpus };
30
- }
31
- function getSandboxResourceConfig() {
32
- return configuredResources;
33
- }
34
- function setSandboxResourceConfig(config) {
35
- const previous = configuredResources;
36
- if (config?.vcpus === void 0) {
37
- configuredResources = void 0;
38
- return previous;
39
- }
40
- if (!Number.isSafeInteger(config.vcpus) || config.vcpus <= 0) {
41
- throw new Error("sandbox.vcpus must be a positive integer");
42
- }
43
- configuredResources = { vcpus: config.vcpus };
44
- return previous;
45
- }
46
- function getSandboxResources() {
47
- return configuredResources ?? resourcesFromEnv();
48
- }
49
-
50
- // src/chat/sandbox/snapshot/resolve.ts
51
- import { Sandbox } from "@vercel/sandbox";
52
- import { z } from "zod";
53
-
54
- // src/chat/sandbox/snapshot/span.ts
55
- function setSnapshotSpanAttributes(snapshot) {
56
- setSpanAttributes({
57
- "app.sandbox.source": snapshot.snapshotId ? "snapshot" : "created",
58
- "app.sandbox.snapshot.cache_hit": snapshot.cacheHit,
59
- "app.sandbox.snapshot.resolve_outcome": snapshot.resolveOutcome,
60
- ...snapshot.profileHash ? { "app.sandbox.snapshot.profile_hash": snapshot.profileHash } : void 0,
61
- "app.sandbox.snapshot.dependency_count": snapshot.dependencyCount,
62
- ...snapshot.rebuildReason ? { "app.sandbox.snapshot.rebuild_reason": snapshot.rebuildReason } : void 0
63
- });
64
- }
65
- async function trace(name, op, attributes, callback) {
66
- return await withSpan(name, op, {}, callback, attributes);
67
- }
68
-
69
- // src/chat/sandbox/snapshot/install.ts
70
- async function runOrThrow(sandbox, params, label) {
71
- const result = await runNonInteractiveCommand(sandbox, params);
72
- if (result.exitCode === 0) {
73
- return;
74
- }
75
- const detail = result.stderr.trim() || result.stdout.trim() || "command failed";
76
- throw new Error(`${label} failed: ${detail}`);
77
- }
78
- async function tryRun(sandbox, params) {
79
- const result = await runNonInteractiveCommand(sandbox, params);
80
- return result.exitCode === 0;
81
- }
82
- async function installGh(sandbox, signal, timeoutMs) {
83
- const installed = await tryRun(sandbox, {
84
- cmd: "dnf",
85
- args: ["install", "-y", "gh"],
86
- signal,
87
- sudo: true,
88
- timeoutMs
89
- });
90
- if (installed) {
91
- return;
92
- }
93
- const repoAdded = await tryRun(sandbox, {
94
- cmd: "dnf",
95
- args: [
96
- "config-manager",
97
- "addrepo",
98
- "--from-repofile=https://cli.github.com/packages/rpm/gh-cli.repo"
99
- ],
100
- signal,
101
- sudo: true,
102
- timeoutMs
103
- });
104
- if (!repoAdded) {
105
- await runOrThrow(
106
- sandbox,
107
- {
108
- cmd: "dnf",
109
- args: ["install", "-y", "dnf-command(config-manager)"],
110
- signal,
111
- sudo: true,
112
- timeoutMs
113
- },
114
- "dnf install dnf-command(config-manager)"
115
- );
116
- await runOrThrow(
117
- sandbox,
118
- {
119
- cmd: "dnf",
120
- args: [
121
- "config-manager",
122
- "--add-repo",
123
- "https://cli.github.com/packages/rpm/gh-cli.repo"
124
- ],
125
- signal,
126
- sudo: true,
127
- timeoutMs
128
- },
129
- "dnf config-manager --add-repo gh-cli.repo"
130
- );
131
- }
132
- await runOrThrow(
133
- sandbox,
134
- {
135
- cmd: "dnf",
136
- args: ["install", "-y", "gh", "--repo", "gh-cli"],
137
- signal,
138
- sudo: true,
139
- timeoutMs
140
- },
141
- "dnf install gh --repo gh-cli"
142
- );
143
- }
144
- function filePath(url, sha256) {
145
- let basename = "package.rpm";
146
- try {
147
- const candidate = new URL(url).pathname.split("/").filter(Boolean).at(-1);
148
- if (candidate) {
149
- basename = candidate;
150
- }
151
- } catch {
152
- }
153
- const sanitized = basename.replace(/[^a-zA-Z0-9._-]/g, "_");
154
- return `/tmp/junior-runtime-${sha256.slice(0, 12)}-${sanitized}`;
155
- }
156
- async function installUrl(sandbox, dependency, signal, timeoutMs) {
157
- const rpmPath = filePath(dependency.url, dependency.sha256);
158
- await runOrThrow(
159
- sandbox,
160
- {
161
- cmd: "curl",
162
- args: ["-fsSL", dependency.url, "-o", rpmPath],
163
- signal,
164
- timeoutMs
165
- },
166
- `curl download ${dependency.url}`
167
- );
168
- const checksum = await runNonInteractiveCommand(sandbox, {
169
- cmd: "sha256sum",
170
- args: [rpmPath],
171
- signal,
172
- timeoutMs
173
- });
174
- const expected = dependency.sha256;
175
- const actual = checksum.stdout.trim().split(/\s+/)[0]?.toLowerCase();
176
- if (checksum.exitCode !== 0) {
177
- const detail = checksum.stderr.trim() || checksum.stdout.trim() || "command failed";
178
- throw new Error(`sha256sum failed: ${detail}`);
179
- }
180
- if (!actual) {
181
- throw new Error("sha256sum produced empty output");
182
- }
183
- if (actual !== expected) {
184
- throw new Error(
185
- `checksum mismatch for ${dependency.url}: expected ${expected}, got ${actual}`
186
- );
187
- }
188
- await runOrThrow(
189
- sandbox,
190
- {
191
- cmd: "dnf",
192
- args: ["install", "-y", rpmPath],
193
- signal,
194
- sudo: true,
195
- timeoutMs
196
- },
197
- `dnf install ${dependency.url}`
198
- );
199
- }
200
- async function dependencies(sandbox, values, signal, timeoutMs) {
201
- const system = values.filter(
202
- (dependency) => dependency.type === "system"
203
- );
204
- const npm = values.filter(
205
- (dependency) => dependency.type === "npm"
206
- ).map((dependency) => `${dependency.package}@${dependency.version}`);
207
- if (system.length > 0) {
208
- await trace(
209
- "sandbox.snapshot.install_system",
210
- "sandbox.snapshot.install.system",
211
- {
212
- "app.sandbox.snapshot.install.system_count": system.length
213
- },
214
- async () => {
215
- for (const dependency of system) {
216
- signal?.throwIfAborted();
217
- if ("url" in dependency) {
218
- await installUrl(sandbox, dependency, signal, timeoutMs);
219
- } else if (dependency.package === "gh") {
220
- await installGh(sandbox, signal, timeoutMs);
221
- } else {
222
- await runOrThrow(
223
- sandbox,
224
- {
225
- cmd: "dnf",
226
- args: ["install", "-y", dependency.package],
227
- signal,
228
- sudo: true,
229
- timeoutMs
230
- },
231
- `dnf install ${dependency.package}`
232
- );
233
- }
234
- }
235
- }
236
- );
237
- }
238
- if (npm.length > 0) {
239
- await trace(
240
- "sandbox.snapshot.install_npm",
241
- "sandbox.snapshot.install.npm",
242
- {
243
- "app.sandbox.snapshot.install.npm_count": npm.length
244
- },
245
- async () => {
246
- await runOrThrow(
247
- sandbox,
248
- {
249
- cmd: "npm",
250
- args: [
251
- "install",
252
- "--global",
253
- "--prefix",
254
- `${SANDBOX_WORKSPACE_ROOT}/.junior`,
255
- ...npm
256
- ],
257
- signal,
258
- timeoutMs
259
- },
260
- "npm install"
261
- );
262
- }
263
- );
264
- }
265
- }
266
- async function postinstall(sandbox, commands, signal, timeoutMs) {
267
- if (commands.length === 0) {
268
- return;
269
- }
270
- await trace(
271
- "sandbox.snapshot.runtime_postinstall",
272
- "sandbox.snapshot.runtime_postinstall",
273
- {
274
- "app.sandbox.snapshot.runtime_postinstall.count": commands.length
275
- },
276
- async () => {
277
- for (const command of commands) {
278
- signal?.throwIfAborted();
279
- const result = await runNonInteractiveCommand(sandbox, {
280
- cmd: command.cmd,
281
- args: command.args,
282
- login: true,
283
- pathPrefix: `${SANDBOX_WORKSPACE_ROOT}/.junior/bin:$PATH`,
284
- signal,
285
- timeoutMs,
286
- ...command.sudo !== void 0 ? { sudo: command.sudo } : void 0
287
- });
288
- if (result.exitCode !== 0) {
289
- const detail = result.stderr.trim() || result.stdout.trim() || "command failed";
290
- throw new Error(
291
- `runtime-postinstall ${command.cmd} failed: ${detail}`
292
- );
293
- }
294
- }
295
- }
296
- );
297
- }
298
-
299
- // src/chat/sandbox/workspace.ts
300
- import {
301
- FileSystem
302
- } from "@vercel/sandbox";
303
- function bindSandboxFileSystem(fs, signal) {
304
- if (!signal) {
305
- return fs;
306
- }
307
- return {
308
- readFile(filePath2, options) {
309
- signal.throwIfAborted();
310
- return fs.readFile(filePath2, { ...options, signal });
311
- },
312
- writeFile(filePath2, content, options) {
313
- signal.throwIfAborted();
314
- return fs.writeFile(filePath2, content, { ...options, signal });
315
- },
316
- readdir(filePath2) {
317
- signal.throwIfAborted();
318
- return fs.readdir(filePath2, { signal });
319
- },
320
- stat(filePath2) {
321
- signal.throwIfAborted();
322
- return fs.stat(filePath2, { signal });
323
- }
324
- };
325
- }
326
- function createSandboxSession(sandbox, options) {
327
- const session = sandbox.currentSession();
328
- const fileSystem = new FileSystem(session);
329
- const run = async (operation) => {
330
- try {
331
- return await operation();
332
- } catch (error) {
333
- if (isSandboxUnavailableError(error)) {
334
- options?.onUnavailable?.(session.sessionId);
335
- }
336
- throw error;
337
- }
338
- };
339
- const fs = {
340
- readFile: async (filePath2, readOptions) => await run(async () => await fileSystem.readFile(filePath2, readOptions)),
341
- writeFile: async (filePath2, content, writeOptions) => await run(
342
- async () => await fileSystem.writeFile(filePath2, content, writeOptions)
343
- ),
344
- readdir: async (filePath2, readOptions) => await run(async () => await fileSystem.readdir(filePath2, readOptions)),
345
- stat: async (filePath2, statOptions) => await run(async () => await fileSystem.stat(filePath2, statOptions))
346
- };
347
- return {
348
- sandboxId: sandbox.name,
349
- sessionId: session.sessionId,
350
- fs,
351
- extendTimeout(duration) {
352
- return run(async () => await session.extendTimeout(duration));
353
- },
354
- mkDir(path) {
355
- return run(async () => await session.mkDir(path));
356
- },
357
- readFileToBuffer(input) {
358
- return run(async () => await session.readFileToBuffer(input));
359
- },
360
- async runCommand(input) {
361
- const result = await run(async () => await session.runCommand(input));
362
- const [stdout, stderr] = await Promise.all([
363
- run(async () => await result.stdout()),
364
- run(async () => await result.stderr())
365
- ]);
366
- return {
367
- exitCode: result.exitCode,
368
- stdout,
369
- stderr
370
- };
371
- },
372
- snapshot(options2) {
373
- return run(async () => {
374
- const snapshot = await session.snapshot(options2);
375
- return { snapshotId: snapshot.snapshotId };
376
- });
377
- },
378
- stop() {
379
- return run(async () => await session.stop());
380
- },
381
- update(params) {
382
- return run(async () => await session.update(params));
383
- },
384
- writeFiles(files) {
385
- return run(async () => await session.writeFiles(files));
386
- }
387
- };
388
- }
389
- async function stopSession(session) {
390
- if (!session) return;
391
- try {
392
- await session.stop();
393
- } catch {
394
- }
395
- }
396
-
397
- // src/chat/sandbox/snapshot/resolve.ts
398
- var SNAPSHOT_CACHE_PREFIX = "junior:sandbox_snapshot_profile:v2";
399
- var SNAPSHOT_LOCK_PREFIX = "junior:sandbox_snapshot_lock";
400
- var SNAPSHOT_CACHE_TTL_MS = 30 * 24 * 60 * 60 * 1e3;
401
- var SNAPSHOT_BUILD_LOCK_BUFFER_MS = 30 * 1e3;
402
- var SNAPSHOT_WAIT_FOR_LOCK_BUFFER_MS = 30 * 1e3;
403
- var cachedSnapshotSchema = z.object({
404
- profileHash: z.string(),
405
- snapshotId: z.string(),
406
- runtime: z.string(),
407
- createdAtMs: z.number(),
408
- dependencyCount: z.number(),
409
- buildDurationMs: z.number().int().nonnegative()
410
- }).strict();
411
- function profileCacheKey(profileHash) {
412
- return `${SNAPSHOT_CACHE_PREFIX}:${profileHash}`;
413
- }
414
- function profileLockKey(profileHash) {
415
- return `${SNAPSHOT_LOCK_PREFIX}:${profileHash}`;
416
- }
417
- async function getCachedSnapshot(profileHash) {
418
- const state = getStateAdapter();
419
- await state.connect();
420
- const raw = await state.get(profileCacheKey(profileHash));
421
- if (typeof raw !== "string") {
422
- return null;
423
- }
424
- let value;
425
- try {
426
- value = JSON.parse(raw);
427
- } catch {
428
- throw new Error(`Invalid cached sandbox snapshot for ${profileHash}`);
429
- }
430
- const parsed = cachedSnapshotSchema.safeParse(value);
431
- if (!parsed.success || parsed.data.profileHash !== profileHash) {
432
- throw new Error(`Invalid cached sandbox snapshot for ${profileHash}`);
433
- }
434
- return parsed.data;
435
- }
436
- async function setCachedSnapshot(entry) {
437
- const state = getStateAdapter();
438
- await state.connect();
439
- await state.set(
440
- profileCacheKey(entry.profileHash),
441
- JSON.stringify(entry),
442
- SNAPSHOT_CACHE_TTL_MS
443
- );
444
- }
445
- async function build(value, runtime, timeoutMs, signal, prepare) {
446
- return await trace(
447
- "sandbox.snapshot.build",
448
- "sandbox.snapshot.build",
449
- {
450
- "app.sandbox.runtime": runtime,
451
- "app.sandbox.snapshot.dependency_count": value.dependencyCount
452
- },
453
- async () => {
454
- const startedAtMs = Date.now();
455
- const sandboxCredentials = getVercelSandboxCredentials();
456
- const resources = getSandboxResources();
457
- const sandbox = createSandboxSession(
458
- await Sandbox.create({
459
- timeout: timeoutMs,
460
- runtime,
461
- signal,
462
- ...sandboxCredentials ?? {},
463
- ...resources ? { resources } : void 0
464
- })
465
- );
466
- try {
467
- await dependencies(sandbox, value.dependencies, signal);
468
- await postinstall(sandbox, value.postinstall, signal);
469
- await prepare?.(sandbox);
470
- const snapshotId = await trace(
471
- "sandbox.snapshot.capture",
472
- "sandbox.snapshot.capture",
473
- {
474
- "app.sandbox.snapshot.dependency_count": value.dependencyCount
475
- },
476
- async () => {
477
- const snapshot = await sandbox.snapshot({ signal });
478
- return snapshot.snapshotId;
479
- }
480
- );
481
- return {
482
- snapshotId,
483
- buildDurationMs: Math.max(0, Date.now() - startedAtMs)
484
- };
485
- } finally {
486
- try {
487
- await sandbox.stop();
488
- } catch {
489
- }
490
- }
491
- }
492
- );
493
- }
494
- async function withBuildLock(profileHash, timeoutMs, callback, canUseCachedSnapshot, onWaitingForLock, signal) {
495
- signal?.throwIfAborted();
496
- const state = getStateAdapter();
497
- await state.connect();
498
- const lockKey = profileLockKey(profileHash);
499
- const lockTtlMs = timeoutMs + SNAPSHOT_BUILD_LOCK_BUFFER_MS;
500
- const tryAcquireLock = async () => await state.acquireLock(lockKey, lockTtlMs);
501
- let lock = await tryAcquireLock();
502
- if (lock) {
503
- try {
504
- return await callback();
505
- } finally {
506
- await state.releaseLock(lock);
507
- }
508
- }
509
- return await trace(
510
- "sandbox.snapshot.lock_wait",
511
- "sandbox.snapshot.lock_wait",
512
- {
513
- "app.sandbox.snapshot.profile_hash": profileHash
514
- },
515
- async () => {
516
- await onWaitingForLock?.();
517
- const waitUntil = Date.now() + lockTtlMs + SNAPSHOT_WAIT_FOR_LOCK_BUFFER_MS;
518
- while (Date.now() < waitUntil) {
519
- signal?.throwIfAborted();
520
- const cached2 = await getCachedSnapshot(profileHash);
521
- if (cached2?.snapshotId && canUseCachedSnapshot(cached2)) {
522
- return {
523
- snapshotId: cached2.snapshotId,
524
- source: "cache_hit_after_lock_wait",
525
- createdAtMs: cached2.createdAtMs,
526
- buildDurationMs: cached2.buildDurationMs
527
- };
528
- }
529
- lock = await tryAcquireLock();
530
- if (lock) {
531
- try {
532
- const result = await callback();
533
- return {
534
- snapshotId: result.snapshotId,
535
- source: result.source === "built" ? "built" : "cache_hit_after_lock_wait",
536
- createdAtMs: result.createdAtMs,
537
- buildDurationMs: result.buildDurationMs
538
- };
539
- } finally {
540
- await state.releaseLock(lock);
541
- }
542
- }
543
- await sleep(500, signal);
544
- }
545
- signal?.throwIfAborted();
546
- const cached = await getCachedSnapshot(profileHash);
547
- if (cached?.snapshotId && canUseCachedSnapshot(cached)) {
548
- return {
549
- snapshotId: cached.snapshotId,
550
- source: "cache_hit_after_lock_wait",
551
- createdAtMs: cached.createdAtMs,
552
- buildDurationMs: cached.buildDurationMs
553
- };
554
- }
555
- throw new Error("Timed out waiting for snapshot build lock");
556
- }
557
- );
558
- }
559
- function toResolveOutcome(forceRebuild, source) {
560
- if (source === "built") {
561
- return forceRebuild ? "forced_rebuild" : "rebuilt";
562
- }
563
- return source;
564
- }
565
- function getRebuildReason(params) {
566
- if (params.forceRebuild) {
567
- return params.staleSnapshotId ? "snapshot_missing" : "force_rebuild";
568
- }
569
- if (params.cached?.snapshotId && params.shouldRebuildCached) {
570
- return "floating_stale";
571
- }
572
- if (!params.cached?.snapshotId) {
573
- return "cache_miss";
574
- }
575
- return void 0;
576
- }
577
- async function resolve(params) {
578
- return await trace(
579
- "sandbox.snapshot.resolve",
580
- "sandbox.snapshot.resolve",
581
- {
582
- "app.sandbox.runtime": params.runtime,
583
- "app.sandbox.snapshot.force_rebuild": Boolean(params.forceRebuild)
584
- },
585
- async () => {
586
- params.signal?.throwIfAborted();
587
- await params.onProgress?.("resolve_start");
588
- const currentProfile = create(params.runtime, params.workspace);
589
- if (!currentProfile) {
590
- return {
591
- dependencyCount: 0,
592
- cacheHit: false,
593
- resolveOutcome: "no_profile"
594
- };
595
- }
596
- const cached = await getCachedSnapshot(currentProfile.hash);
597
- const cachedNeedsRebuild = Boolean(
598
- cached?.snapshotId && isStale(currentProfile, cached.createdAtMs)
599
- );
600
- if (!params.forceRebuild && cached?.snapshotId && !cachedNeedsRebuild) {
601
- await params.onProgress?.("cache_hit");
602
- return {
603
- snapshotId: cached.snapshotId,
604
- profileHash: currentProfile.hash,
605
- dependencyCount: currentProfile.dependencyCount,
606
- cacheHit: true,
607
- resolveOutcome: "cache_hit",
608
- createdAtMs: cached.createdAtMs,
609
- buildDurationMs: cached.buildDurationMs
610
- };
611
- }
612
- const rebuildReason = getRebuildReason({
613
- forceRebuild: params.forceRebuild,
614
- staleSnapshotId: params.staleSnapshotId,
615
- cached,
616
- shouldRebuildCached: cachedNeedsRebuild
617
- });
618
- const canUseCachedSnapshot = (candidate) => {
619
- if (params.forceRebuild) {
620
- if (params.staleSnapshotId) {
621
- return candidate.snapshotId !== params.staleSnapshotId;
622
- }
623
- return candidate.snapshotId !== cached?.snapshotId;
624
- }
625
- return !isStale(currentProfile, candidate.createdAtMs);
626
- };
627
- const lockResult = await withBuildLock(
628
- currentProfile.hash,
629
- params.timeoutMs,
630
- async () => {
631
- const latest = await getCachedSnapshot(currentProfile.hash);
632
- if (latest?.snapshotId && canUseCachedSnapshot(latest)) {
633
- await params.onProgress?.("cache_hit");
634
- return {
635
- snapshotId: latest.snapshotId,
636
- source: "cache_hit",
637
- createdAtMs: latest.createdAtMs,
638
- buildDurationMs: latest.buildDurationMs
639
- };
640
- }
641
- await params.onProgress?.("building_snapshot");
642
- const built = await build(
643
- currentProfile,
644
- params.runtime,
645
- params.timeoutMs,
646
- params.signal,
647
- params.prepareWorkspace
648
- );
649
- const createdAtMs = Date.now();
650
- await setCachedSnapshot({
651
- profileHash: currentProfile.hash,
652
- snapshotId: built.snapshotId,
653
- runtime: params.runtime,
654
- createdAtMs,
655
- dependencyCount: currentProfile.dependencyCount,
656
- buildDurationMs: built.buildDurationMs
657
- });
658
- await params.onProgress?.("build_complete");
659
- return {
660
- snapshotId: built.snapshotId,
661
- source: "built",
662
- createdAtMs,
663
- buildDurationMs: built.buildDurationMs
664
- };
665
- },
666
- canUseCachedSnapshot,
667
- async () => {
668
- await params.onProgress?.("waiting_for_lock");
669
- },
670
- params.signal
671
- );
672
- return {
673
- snapshotId: lockResult.snapshotId,
674
- profileHash: currentProfile.hash,
675
- dependencyCount: currentProfile.dependencyCount,
676
- cacheHit: lockResult.source !== "built",
677
- resolveOutcome: toResolveOutcome(
678
- Boolean(params.forceRebuild),
679
- lockResult.source
680
- ),
681
- createdAtMs: lockResult.createdAtMs,
682
- buildDurationMs: lockResult.buildDurationMs,
683
- ...rebuildReason ? { rebuildReason } : void 0
684
- };
685
- }
686
- );
687
- }
688
- function isMissingError(error) {
689
- const searchable = error instanceof Error ? error.message.toLowerCase() : String(error).toLowerCase();
690
- return searchable.includes("snapshot") && (searchable.includes("not found") || searchable.includes("unknown") || searchable.includes("404"));
691
- }
692
-
693
- export {
694
- getSandboxResourceConfig,
695
- setSandboxResourceConfig,
696
- getSandboxResources,
697
- setSnapshotSpanAttributes,
698
- dependencies,
699
- postinstall,
700
- bindSandboxFileSystem,
701
- createSandboxSession,
702
- stopSession,
703
- getCachedSnapshot,
704
- resolve,
705
- isMissingError
706
- };