@sentry/junior 0.170.0 → 0.172.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/dist/{agent-hooks-IPUNCZPZ.js → agent-hooks-IZMIMXUX.js} +15 -10
  2. package/dist/api.js +31 -30
  3. package/dist/app.js +32 -32
  4. package/dist/{catalog-runtime-E6XHWRPG.js → catalog-runtime-PDNXCNCJ.js} +5 -5
  5. package/dist/chat/sandbox/snapshot/store.d.ts +28 -0
  6. package/dist/chat/workspaces/store.d.ts +1 -10
  7. package/dist/chat/workspaces/types.d.ts +14 -1
  8. package/dist/{chunk-NESGW5HV.js → chunk-27T2WQJV.js} +1 -1
  9. package/dist/{chunk-47GJ7QRO.js → chunk-6RWQHBTV.js} +1 -1
  10. package/dist/{chunk-TX553KXA.js → chunk-A6AJ354O.js} +5 -5
  11. package/dist/{chunk-IJTFG6AK.js → chunk-AHWLGR5T.js} +5 -9
  12. package/dist/{chunk-CA6JIB7S.js → chunk-AQ4GXXRD.js} +21 -21
  13. package/dist/{chunk-3SFZJVX5.js → chunk-BTD6ZYFL.js} +2 -2
  14. package/dist/{chunk-E7HKIHI5.js → chunk-CBPREIWS.js} +2 -2
  15. package/dist/{chunk-7TVGQZOH.js → chunk-CO47EWFW.js} +4 -4
  16. package/dist/{chunk-2XI6OLXA.js → chunk-CUJ2T7FO.js} +9 -9
  17. package/dist/{chunk-F4UM52UH.js → chunk-ELAP5LB5.js} +1 -1
  18. package/dist/{chunk-BW644E3V.js → chunk-EXEO2R4S.js} +1 -1
  19. package/dist/{chunk-4PSUCN4P.js → chunk-FESC2EW7.js} +1 -1
  20. package/dist/{chunk-74XMBKRI.js → chunk-FUYKKSDV.js} +1 -1
  21. package/dist/{chunk-6GOKKLWF.js → chunk-G2DJ7LUE.js} +6 -6
  22. package/dist/{chunk-HZALSYOW.js → chunk-G4GNP4Q2.js} +5 -5
  23. package/dist/{chunk-6E4WQV75.js → chunk-HEOOUGVL.js} +1 -1
  24. package/dist/{chunk-5EPG7PYS.js → chunk-IAOQPDO6.js} +1 -1
  25. package/dist/chunk-IFSKN5VH.js +399 -0
  26. package/dist/{chunk-YWX7D7BJ.js → chunk-JOSDA5SZ.js} +17 -17
  27. package/dist/{chunk-6W2UIZSA.js → chunk-LVNMMESU.js} +70 -11
  28. package/dist/{chunk-UD4BNNM2.js → chunk-MNYAYK5I.js} +1 -1
  29. package/dist/{chunk-A22DGDXT.js → chunk-NB7WS4SP.js} +1 -1
  30. package/dist/{chunk-T4SEUU7A.js → chunk-Q36YWAJT.js} +1 -1
  31. package/dist/{chunk-NGL4XFT2.js → chunk-QAEKVEZY.js} +1 -1
  32. package/dist/{chunk-B53NR3XY.js → chunk-QBHPQCEQ.js} +6 -270
  33. package/dist/{chunk-NFERKIUX.js → chunk-QCGDWFYC.js} +4 -4
  34. package/dist/{chunk-KQCHIOME.js → chunk-SU7QH274.js} +8 -8
  35. package/dist/{chunk-IF3OK4XO.js → chunk-TWIRPYVB.js} +6 -6
  36. package/dist/{chunk-FKOLWEMX.js → chunk-W6THM2TX.js} +5 -5
  37. package/dist/{chunk-UHW5RAIB.js → chunk-XSO5JEHI.js} +12 -12
  38. package/dist/{chunk-IX7VHMIJ.js → chunk-Y4AEFUEV.js} +3 -3
  39. package/dist/{chunk-F3I6YFB4.js → chunk-YRBLN5PJ.js} +182 -68
  40. package/dist/cli/chat.js +30 -30
  41. package/dist/cli/check.js +6 -6
  42. package/dist/cli/plugins.js +13 -13
  43. package/dist/cli/snapshot-create.js +12 -11
  44. package/dist/cli/upgrade.js +7 -7
  45. package/dist/db/schema/snapshots.d.ts +254 -0
  46. package/dist/db/schema/workspaces.d.ts +0 -68
  47. package/dist/db/schema.d.ts +251 -69
  48. package/dist/{db-WMSEGSFM.js → db-32P3ZO4Z.js} +7 -7
  49. package/dist/instrumentation.js +4 -4
  50. package/dist/nitro.js +2 -2
  51. package/dist/{oauth-callback-server-GBS47NTO.js → oauth-callback-server-ZOHC35HH.js} +23 -23
  52. package/dist/{runner-V2A2Z7K3.js → runner-QWGQH425.js} +17 -13
  53. package/dist/{skills-Z35YXLUG.js → skills-2T6JZT2K.js} +6 -6
  54. package/dist/spawn-55U4TVHQ.js +37 -0
  55. package/dist/{validation-EQCK4DA5.js → validation-LMGCYHRK.js} +6 -6
  56. package/dist/version.js +1 -1
  57. package/dist/{work-XIANCABO.js → work-CVXCACZK.js} +18 -18
  58. package/dist/worker-SWMVAAN6.js +24 -0
  59. package/migrations/0032_workspace_snapshots_table.sql +69 -0
  60. package/migrations/meta/0032_snapshot.json +2892 -0
  61. package/migrations/meta/_journal.json +8 -1
  62. package/package.json +4 -4
  63. package/dist/chunk-BVREIWBD.js +0 -131
  64. package/dist/spawn-AKPJBUS2.js +0 -37
  65. package/dist/worker-YALLEN2Z.js +0 -24
@@ -0,0 +1,399 @@
1
+ import {
2
+ pluginCatalogRuntime
3
+ } from "./chunk-HEOOUGVL.js";
4
+
5
+ // src/chat/sandbox/paths.ts
6
+ function normalizeWorkspaceRoot(input) {
7
+ const candidate = (input ?? "").trim();
8
+ if (!candidate) {
9
+ return "/vercel/sandbox";
10
+ }
11
+ const normalized = candidate.replace(/\/+$/, "");
12
+ return normalized.startsWith("/") ? normalized : `/${normalized}`;
13
+ }
14
+ var SANDBOX_WORKSPACE_ROOT = normalizeWorkspaceRoot(
15
+ process.env.VERCEL_SANDBOX_WORKSPACE_DIR
16
+ );
17
+ var SANDBOX_REPOS_ROOT = `${SANDBOX_WORKSPACE_ROOT}/repos`;
18
+ var SANDBOX_SKILLS_ROOT = `${SANDBOX_WORKSPACE_ROOT}/skills`;
19
+ var SANDBOX_DATA_ROOT = `${SANDBOX_WORKSPACE_ROOT}/data`;
20
+ function sandboxSkillDir(skillName) {
21
+ return `${SANDBOX_SKILLS_ROOT}/${skillName}`;
22
+ }
23
+ function sandboxSkillFile(skillName) {
24
+ return `${sandboxSkillDir(skillName)}/SKILL.md`;
25
+ }
26
+ function sandboxSkillPathResolution(skillName) {
27
+ const skillDir = sandboxSkillDir(skillName);
28
+ return `Resolve relative paths in this skill against ${skillDir}. For bash commands from this skill, cd to ${skillDir} first or use absolute paths.`;
29
+ }
30
+
31
+ // src/chat/sandbox/noninteractive-command.ts
32
+ var NON_INTERACTIVE_ENV = {
33
+ CI: "1",
34
+ TERM: "dumb",
35
+ NO_COLOR: "1",
36
+ PAGER: "cat",
37
+ GIT_PAGER: "cat",
38
+ GH_PROMPT_DISABLED: "1",
39
+ GH_NO_UPDATE_NOTIFIER: "1",
40
+ GH_NO_EXTENSION_UPDATE_NOTIFIER: "1",
41
+ GH_SPINNER_DISABLED: "1",
42
+ GIT_TERMINAL_PROMPT: "0",
43
+ GCM_INTERACTIVE: "never",
44
+ DEBIAN_FRONTEND: "noninteractive",
45
+ // Git credential isolation: prevent git from sending its own auth so the
46
+ // sandbox egress proxy's header transforms are the sole credential source.
47
+ GIT_ASKPASS: "/bin/true",
48
+ GIT_CONFIG_NOSYSTEM: "1",
49
+ GIT_CONFIG_COUNT: "2",
50
+ GIT_CONFIG_KEY_0: "credential.helper",
51
+ GIT_CONFIG_VALUE_0: "",
52
+ GIT_CONFIG_KEY_1: "http.emptyAuth",
53
+ GIT_CONFIG_VALUE_1: "true"
54
+ };
55
+ function shellQuote(value) {
56
+ return `'${value.replace(/'/g, "'\\''")}'`;
57
+ }
58
+ function buildEnvExports(options) {
59
+ const lines = [];
60
+ if (options.pathPrefix) {
61
+ lines.push(`export PATH="${options.pathPrefix}"`);
62
+ }
63
+ for (const [key, value] of Object.entries(NON_INTERACTIVE_ENV)) {
64
+ lines.push(`export ${key}=${shellQuote(value)}`);
65
+ }
66
+ for (const [key, value] of Object.entries(options.env ?? {})) {
67
+ lines.push(`export ${key}=${shellQuote(value)}`);
68
+ }
69
+ return lines;
70
+ }
71
+ function buildCommandScript(input) {
72
+ return [shellQuote(input.cmd), ...(input.args ?? []).map(shellQuote)].join(
73
+ " "
74
+ );
75
+ }
76
+ function buildNonInteractiveShellScript(script, options = {}) {
77
+ return [...buildEnvExports(options), "exec </dev/null", script].join(" && ");
78
+ }
79
+ function buildNonInteractiveCommand(input) {
80
+ return {
81
+ cmd: "bash",
82
+ args: [
83
+ input.login ? "-lc" : "-c",
84
+ buildNonInteractiveShellScript(buildCommandScript(input), {
85
+ env: input.env,
86
+ pathPrefix: input.pathPrefix
87
+ })
88
+ ]
89
+ };
90
+ }
91
+ async function runNonInteractiveCommand(sandbox, input) {
92
+ const command = {
93
+ ...buildNonInteractiveCommand(input),
94
+ ...input.cwd ? { cwd: input.cwd } : {},
95
+ ...input.signal ? { signal: input.signal } : {},
96
+ ...input.sudo !== void 0 ? { sudo: input.sudo } : {}
97
+ };
98
+ return await sandbox.runCommand(command);
99
+ }
100
+
101
+ // src/chat/sandbox/snapshot/profile.ts
102
+ import { createHash } from "crypto";
103
+
104
+ // src/chat/sandbox/docker.ts
105
+ var DOCKER_DAEMON_JSON = `{
106
+ "storage-driver": "overlay2",
107
+ "live-restore": false
108
+ }
109
+ `;
110
+ var DOCKER_ENSURE_SCRIPT = `#!/bin/sh
111
+ set -eu
112
+
113
+ if [ "$(id -u)" -ne 0 ]; then
114
+ exec sudo -n "$0" "$@"
115
+ fi
116
+
117
+ SOCK=/var/run/docker.sock
118
+ PIDFILE=/var/run/docker.pid
119
+ LOG=/var/log/junior-dockerd.log
120
+
121
+ is_ready() {
122
+ [ -S "$SOCK" ] && /usr/bin/docker info >/dev/null 2>&1
123
+ }
124
+
125
+ if is_ready; then
126
+ chmod 666 "$SOCK" 2>/dev/null || true
127
+ exit 0
128
+ fi
129
+
130
+ mkdir -p /etc/docker /var/lib/docker /var/run /var/log
131
+ if [ ! -f /etc/docker/daemon.json ]; then
132
+ cat > /etc/docker/daemon.json <<'EOF'
133
+ {
134
+ "storage-driver": "overlay2",
135
+ "live-restore": false
136
+ }
137
+ EOF
138
+ fi
139
+
140
+ if [ -f "$PIDFILE" ]; then
141
+ oldpid="$(cat "$PIDFILE" 2>/dev/null || true)"
142
+ if [ -n "\${oldpid:-}" ] && ! kill -0 "$oldpid" 2>/dev/null; then
143
+ rm -f "$PIDFILE"
144
+ fi
145
+ fi
146
+
147
+ if [ ! -f "$PIDFILE" ] || ! kill -0 "$(cat "$PIDFILE" 2>/dev/null)" 2>/dev/null; then
148
+ # dockerd must outlive this helper; nohup + background is intentional.
149
+ nohup dockerd --host="unix://$SOCK" --pidfile="$PIDFILE" >"$LOG" 2>&1 &
150
+ fi
151
+
152
+ i=0
153
+ while [ "$i" -lt 50 ]; do
154
+ if is_ready; then
155
+ chmod 666 "$SOCK" 2>/dev/null || true
156
+ exit 0
157
+ fi
158
+ i=$((i + 1))
159
+ sleep 0.1
160
+ done
161
+
162
+ echo "junior-ensure-docker: dockerd failed to become ready" >&2
163
+ if [ -f "$LOG" ]; then
164
+ tail -n 50 "$LOG" >&2 || true
165
+ fi
166
+ exit 1
167
+ `;
168
+ var DOCKER_CLI_WRAPPER_SCRIPT = `#!/bin/sh
169
+ set -eu
170
+ if command -v junior-ensure-docker >/dev/null 2>&1; then
171
+ junior-ensure-docker
172
+ fi
173
+ exec /usr/bin/docker "$@"
174
+ `;
175
+ var DOCKER_COMPOSE_CLI_WRAPPER_SCRIPT = `#!/bin/sh
176
+ set -eu
177
+ if command -v junior-ensure-docker >/dev/null 2>&1; then
178
+ junior-ensure-docker
179
+ fi
180
+ exec /usr/local/libexec/junior-docker-compose "$@"
181
+ `;
182
+ async function ensureDockerDaemon(sandbox, signal) {
183
+ await runNonInteractiveCommand(sandbox, {
184
+ cmd: "sh",
185
+ args: [
186
+ "-c",
187
+ "command -v junior-ensure-docker >/dev/null 2>&1 && junior-ensure-docker || true"
188
+ ],
189
+ signal
190
+ });
191
+ }
192
+
193
+ // src/chat/sandbox/runtime-dependencies.ts
194
+ var GLOBAL_RUNTIME_DEPENDENCIES = [
195
+ { type: "system", package: "docker" },
196
+ { type: "system", package: "spal-release" },
197
+ { type: "system", package: "ripgrep" }
198
+ ];
199
+ function writeFileCommand(path, contents, mode = "0644") {
200
+ const payload = Buffer.from(contents, "utf8").toString("base64");
201
+ return [
202
+ `printf '%s' '${payload}' | base64 -d > ${path}`,
203
+ `chmod ${mode} ${path}`
204
+ ].join("\n");
205
+ }
206
+ function writeExecutableCommand(path, contents) {
207
+ return writeFileCommand(path, contents, "0755");
208
+ }
209
+ var GLOBAL_RUNTIME_POSTINSTALL = [
210
+ {
211
+ cmd: "sh",
212
+ args: [
213
+ "-c",
214
+ [
215
+ "set -eu",
216
+ 'case "$(uname -m)" in',
217
+ ' x86_64) asset="x86_64"; sha256="7af95166a730b87e172d4fc9aefea8725d3c6c7327d59149267b452114ddb7d4" ;;',
218
+ ' aarch64) asset="aarch64"; sha256="49082844b87f03cdcd5f5bbef1ba8c9c897b7a2dfb80cea18d61ec8ca6117e0c" ;;',
219
+ ' *) echo "unsupported Docker Compose architecture: $(uname -m)" >&2; exit 1 ;;',
220
+ "esac",
221
+ 'tmp="$(mktemp)"',
222
+ `trap 'rm -f "$tmp"' EXIT`,
223
+ 'curl --fail --location --silent --show-error "https://github.com/docker/compose/releases/download/v2.39.4/docker-compose-linux-${asset}" --output "$tmp"',
224
+ 'echo "${sha256} ${tmp}" | sha256sum --check --status',
225
+ // Keep the real Compose binary off PATH; the wrapper below starts dockerd.
226
+ 'install -D -m 0755 "$tmp" /usr/local/libexec/junior-docker-compose',
227
+ "mkdir -p /usr/local/lib/docker/cli-plugins /usr/local/libexec /etc/docker /usr/local/bin",
228
+ `mkdir -p ${SANDBOX_WORKSPACE_ROOT}/.junior/bin`,
229
+ writeFileCommand("/etc/docker/daemon.json", DOCKER_DAEMON_JSON),
230
+ writeExecutableCommand(
231
+ "/usr/local/bin/junior-ensure-docker",
232
+ DOCKER_ENSURE_SCRIPT
233
+ ),
234
+ // docker compose plugin delegates to the real Compose binary.
235
+ "ln -sfn /usr/local/libexec/junior-docker-compose /usr/local/lib/docker/cli-plugins/docker-compose",
236
+ // PATH wrappers auto-start dockerd for both CLI entrypoints.
237
+ writeExecutableCommand(
238
+ "/usr/local/bin/docker-compose",
239
+ DOCKER_COMPOSE_CLI_WRAPPER_SCRIPT
240
+ ),
241
+ writeExecutableCommand(
242
+ `${SANDBOX_WORKSPACE_ROOT}/.junior/bin/docker`,
243
+ DOCKER_CLI_WRAPPER_SCRIPT
244
+ ),
245
+ writeExecutableCommand(
246
+ `${SANDBOX_WORKSPACE_ROOT}/.junior/bin/docker-compose`,
247
+ DOCKER_COMPOSE_CLI_WRAPPER_SCRIPT
248
+ ),
249
+ // Prefer the wrapper over /usr/bin/docker for non-login shells too.
250
+ writeExecutableCommand(
251
+ "/usr/local/bin/docker",
252
+ DOCKER_CLI_WRAPPER_SCRIPT
253
+ )
254
+ ].join("\n")
255
+ ],
256
+ sudo: true
257
+ }
258
+ ];
259
+
260
+ // src/chat/sandbox/snapshot/profile.ts
261
+ var VERSION = 1;
262
+ var DEFAULT_FLOATING_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1e3;
263
+ function isExactNpmVersion(version) {
264
+ return /^\d+\.\d+\.\d+(?:[-+][a-z0-9.]+)?$/i.test(version.trim());
265
+ }
266
+ function isFloating(dep) {
267
+ return dep.type === "npm" && !isExactNpmVersion(dep.version);
268
+ }
269
+ function mergeDependencies(dependencies) {
270
+ const seen = /* @__PURE__ */ new Set();
271
+ const npmVersions = /* @__PURE__ */ new Map();
272
+ const merged = [];
273
+ for (const dependency of dependencies) {
274
+ const key = dependency.type === "npm" ? `${dependency.type}:${dependency.package}:${dependency.version}` : "package" in dependency ? `${dependency.type}:package:${dependency.package}` : `${dependency.type}:url:${dependency.url}:${dependency.sha256}`;
275
+ if (seen.has(key)) {
276
+ continue;
277
+ }
278
+ seen.add(key);
279
+ if (dependency.type === "npm") {
280
+ const version = npmVersions.get(dependency.package);
281
+ if (version !== void 0 && version !== dependency.version) {
282
+ throw new Error(
283
+ `Conflicting runtime dependency versions for ${dependency.package}: ${version} and ${dependency.version}`
284
+ );
285
+ }
286
+ npmVersions.set(dependency.package, dependency.version);
287
+ }
288
+ merged.push(dependency);
289
+ }
290
+ return merged;
291
+ }
292
+ function floatingMaxAgeMs() {
293
+ const raw = process.env.SANDBOX_SNAPSHOT_FLOATING_MAX_AGE_MS;
294
+ if (!raw?.trim()) {
295
+ return DEFAULT_FLOATING_MAX_AGE_MS;
296
+ }
297
+ const parsed = Number.parseInt(raw, 10);
298
+ return Number.isFinite(parsed) && parsed >= 0 ? parsed : DEFAULT_FLOATING_MAX_AGE_MS;
299
+ }
300
+ function compareCodePoints(left, right) {
301
+ if (left < right) return -1;
302
+ if (left > right) return 1;
303
+ return 0;
304
+ }
305
+ function workspaceRecipe(workspace) {
306
+ const repos = [...workspace.repos].map(({ provider, repo }) => ({
307
+ provider,
308
+ repo
309
+ })).sort((left, right) => {
310
+ const provider = compareCodePoints(left.provider, right.provider);
311
+ if (provider !== 0) return provider;
312
+ return compareCodePoints(left.repo, right.repo);
313
+ });
314
+ return {
315
+ id: workspace.id,
316
+ repos,
317
+ setupScript: workspace.setupScript
318
+ };
319
+ }
320
+ function create(runtime, workspace) {
321
+ const dependencies = mergeDependencies([
322
+ ...GLOBAL_RUNTIME_DEPENDENCIES,
323
+ ...pluginCatalogRuntime.getRuntimeDependencies()
324
+ ]);
325
+ const pluginPostinstall = pluginCatalogRuntime.getRuntimePostinstall();
326
+ const postinstall = [...GLOBAL_RUNTIME_POSTINSTALL, ...pluginPostinstall];
327
+ if (dependencies.length === 0 && postinstall.length === 0 && !workspace) {
328
+ return null;
329
+ }
330
+ const rebuildEpoch = process.env.SANDBOX_SNAPSHOT_REBUILD_EPOCH?.trim() ?? "";
331
+ const floating = dependencies.some((dependency) => isFloating(dependency)) || pluginPostinstall.length > 0 || Boolean(workspace);
332
+ const hash2 = createHash("sha256").update(
333
+ JSON.stringify({
334
+ version: VERSION,
335
+ runtime,
336
+ rebuildEpoch,
337
+ dependencies,
338
+ postinstall,
339
+ ...workspace ? { workspace: workspaceRecipe(workspace) } : {}
340
+ })
341
+ ).digest("hex");
342
+ return {
343
+ hash: hash2,
344
+ dependencyCount: dependencies.length,
345
+ floating,
346
+ dependencies,
347
+ postinstall
348
+ };
349
+ }
350
+ function hash(runtime, workspace) {
351
+ return create(runtime, workspace)?.hash;
352
+ }
353
+ function isStale(profile, createdAtMs) {
354
+ if (!profile.floating) {
355
+ return false;
356
+ }
357
+ const maxAgeMs = floatingMaxAgeMs();
358
+ return maxAgeMs === 0 || Date.now() - createdAtMs > maxAgeMs;
359
+ }
360
+
361
+ // src/chat/sleep.ts
362
+ function sleep(ms, signal) {
363
+ if (!signal) {
364
+ return new Promise((resolve) => setTimeout(resolve, ms));
365
+ }
366
+ return new Promise((resolve, reject) => {
367
+ if (signal.aborted) {
368
+ reject(signal.reason);
369
+ return;
370
+ }
371
+ const timeoutId = setTimeout(() => {
372
+ signal.removeEventListener("abort", onAbort);
373
+ resolve();
374
+ }, ms);
375
+ const onAbort = () => {
376
+ clearTimeout(timeoutId);
377
+ reject(signal.reason);
378
+ };
379
+ signal.addEventListener("abort", onAbort, { once: true });
380
+ });
381
+ }
382
+
383
+ export {
384
+ SANDBOX_WORKSPACE_ROOT,
385
+ SANDBOX_REPOS_ROOT,
386
+ SANDBOX_SKILLS_ROOT,
387
+ SANDBOX_DATA_ROOT,
388
+ sandboxSkillDir,
389
+ sandboxSkillFile,
390
+ sandboxSkillPathResolution,
391
+ sleep,
392
+ buildCommandScript,
393
+ buildNonInteractiveShellScript,
394
+ runNonInteractiveCommand,
395
+ ensureDockerDaemon,
396
+ create,
397
+ hash,
398
+ isStale
399
+ };
@@ -3,15 +3,15 @@ import {
3
3
  } from "./chunk-FA6POGLH.js";
4
4
  import {
5
5
  getTurnRequestDeadline
6
- } from "./chunk-T4SEUU7A.js";
6
+ } from "./chunk-Q36YWAJT.js";
7
7
  import {
8
8
  buildSentryConversationUrl,
9
9
  deleteWebAuthorization
10
- } from "./chunk-NESGW5HV.js";
10
+ } from "./chunk-27T2WQJV.js";
11
11
  import {
12
12
  ensureConversationWake,
13
13
  requestConversationWork
14
- } from "./chunk-7TVGQZOH.js";
14
+ } from "./chunk-CO47EWFW.js";
15
15
  import {
16
16
  buildDeliveredTurnStatePatch,
17
17
  finalizeFailedTurnReplyWithEvent,
@@ -24,7 +24,7 @@ import {
24
24
  requireTurnFailureEventId,
25
25
  resolveTurnSessionRouting,
26
26
  scheduleSessionCompletedPluginTasks
27
- } from "./chunk-2XI6OLXA.js";
27
+ } from "./chunk-CUJ2T7FO.js";
28
28
  import {
29
29
  ConversationTurnLifecycleService,
30
30
  coerceThreadConversationState,
@@ -33,7 +33,7 @@ import {
33
33
  getPersistedSandboxState,
34
34
  getPersistedThreadState,
35
35
  persistThreadStateById
36
- } from "./chunk-TX553KXA.js";
36
+ } from "./chunk-A6AJ354O.js";
37
37
  import {
38
38
  getVercelConversationWorkQueue
39
39
  } from "./chunk-WR76IVA5.js";
@@ -47,7 +47,7 @@ import {
47
47
  lookupSlackUserProfile,
48
48
  resolvePluginOAuthAccount,
49
49
  runAgentWithTimeout
50
- } from "./chunk-KQCHIOME.js";
50
+ } from "./chunk-SU7QH274.js";
51
51
  import {
52
52
  RetryableDeliveryError
53
53
  } from "./chunk-RF6J3DIO.js";
@@ -63,13 +63,13 @@ import {
63
63
  removeReactionFromMessage,
64
64
  resolveBaseUrl,
65
65
  truncateStatusText
66
- } from "./chunk-6GOKKLWF.js";
66
+ } from "./chunk-G2DJ7LUE.js";
67
67
  import {
68
68
  parseSlackThreadId,
69
69
  readSlackRawMessageContext,
70
70
  resolveSlackChannelIdFromMessage,
71
71
  resolveSlackChannelIdFromThreadId
72
- } from "./chunk-4PSUCN4P.js";
72
+ } from "./chunk-FESC2EW7.js";
73
73
  import {
74
74
  CooperativeTurnYieldError,
75
75
  TurnSliceLimitExceededError,
@@ -96,7 +96,7 @@ import {
96
96
  recordTurnSummary,
97
97
  saveTurnCheckpoint,
98
98
  turnHasReply
99
- } from "./chunk-HZALSYOW.js";
99
+ } from "./chunk-G4GNP4Q2.js";
100
100
  import {
101
101
  SlackActionError,
102
102
  getDashboardConversationLink,
@@ -105,18 +105,18 @@ import {
105
105
  getSlackClient,
106
106
  isDmChannel,
107
107
  normalizeSlackConversationId
108
- } from "./chunk-F3I6YFB4.js";
108
+ } from "./chunk-YRBLN5PJ.js";
109
109
  import {
110
110
  getConversationEventStore,
111
111
  getSqlExecutor,
112
112
  requireSlackDestination,
113
113
  upsertIdentity,
114
114
  upsertLinkedIdentity
115
- } from "./chunk-IX7VHMIJ.js";
115
+ } from "./chunk-Y4AEFUEV.js";
116
116
  import {
117
117
  acquireActiveLock,
118
118
  getStateAdapter
119
- } from "./chunk-74XMBKRI.js";
119
+ } from "./chunk-FUYKKSDV.js";
120
120
  import {
121
121
  botConfig,
122
122
  escapeXml,
@@ -124,18 +124,18 @@ import {
124
124
  getRuntimeMetadata,
125
125
  normalizeSlackEmojiName,
126
126
  standardModelId
127
- } from "./chunk-E7HKIHI5.js";
127
+ } from "./chunk-CBPREIWS.js";
128
128
  import {
129
129
  discoverSkills
130
- } from "./chunk-3SFZJVX5.js";
130
+ } from "./chunk-BTD6ZYFL.js";
131
131
  import {
132
132
  pluginCatalogRuntime
133
- } from "./chunk-6E4WQV75.js";
133
+ } from "./chunk-HEOOUGVL.js";
134
134
  import {
135
135
  buildOAuthTokenRequest,
136
136
  hasRequiredOAuthScope,
137
137
  parseOAuthTokenResponse
138
- } from "./chunk-A22DGDXT.js";
138
+ } from "./chunk-NB7WS4SP.js";
139
139
  import {
140
140
  createSlackResumeActor,
141
141
  isUserActor,
@@ -151,7 +151,7 @@ import {
151
151
  setTags,
152
152
  toOptionalString,
153
153
  withLogContext
154
- } from "./chunk-5EPG7PYS.js";
154
+ } from "./chunk-IAOQPDO6.js";
155
155
  import {
156
156
  homeDir
157
157
  } from "./chunk-H4HBKISO.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  DEFAULT_SQL_STATEMENT_TIMEOUT_MS
3
- } from "./chunk-E7HKIHI5.js";
3
+ } from "./chunk-CBPREIWS.js";
4
4
  import {
5
5
  juniorDestinations,
6
6
  timestamptz
@@ -645,25 +645,25 @@ var juniorSchedulerRuns = pgTable16(
645
645
  ]
646
646
  );
647
647
 
648
- // src/db/schema/workspaces.ts
648
+ // src/db/schema/snapshots.ts
649
+ import { sql as sql6 } from "drizzle-orm";
649
650
  import {
651
+ check as check2,
652
+ index as index13,
650
653
  integer as integer6,
651
- pgTable as pgTable17,
652
- primaryKey as primaryKey9,
653
- text as text17,
654
- uniqueIndex as uniqueIndex7
654
+ pgTable as pgTable18,
655
+ text as text18,
656
+ uniqueIndex as uniqueIndex8
655
657
  } from "drizzle-orm/pg-core";
658
+
659
+ // src/db/schema/workspaces.ts
660
+ import { pgTable as pgTable17, primaryKey as primaryKey9, text as text17, uniqueIndex as uniqueIndex7 } from "drizzle-orm/pg-core";
656
661
  var juniorWorkspaces = pgTable17(
657
662
  "junior_workspaces",
658
663
  {
659
664
  id: text17("id").primaryKey(),
660
665
  name: text17("name").notNull(),
661
666
  setupScript: text17("setup_script").notNull().default(""),
662
- // Last successful Workspace snapshot for the dashboard. Resolve still uses Redis.
663
- snapshotId: text17("snapshot_id"),
664
- snapshotGeneratedAt: timestamptz("snapshot_generated_at"),
665
- snapshotBuildDurationMs: integer6("snapshot_build_duration_ms"),
666
- snapshotProfileHash: text17("snapshot_profile_hash"),
667
667
  createdAt: timestamptz("created_at").notNull(),
668
668
  updatedAt: timestamptz("updated_at").notNull()
669
669
  },
@@ -681,6 +681,63 @@ var juniorWorkspaceRepos = pgTable17(
681
681
  ]
682
682
  );
683
683
 
684
+ // src/db/schema/snapshots.ts
685
+ var juniorSnapshots = pgTable18(
686
+ "junior_snapshots",
687
+ {
688
+ id: text18("id").primaryKey(),
689
+ workspaceId: text18("workspace_id").notNull().references(() => juniorWorkspaces.id, { onDelete: "cascade" }),
690
+ profileHash: text18("profile_hash").notNull(),
691
+ status: text18("status").$type().notNull(),
692
+ // Ready artifact facts.
693
+ snapshotId: text18("snapshot_id"),
694
+ buildDurationMs: integer6("build_duration_ms"),
695
+ generatedAt: timestamptz("generated_at"),
696
+ // In-flight builder references for check-in across execution slices.
697
+ buildStartedAt: timestamptz("build_started_at"),
698
+ buildPhase: text18("build_phase").$type(),
699
+ buildSandboxName: text18("build_sandbox_name"),
700
+ buildCommandId: text18("build_command_id"),
701
+ buildError: text18("build_error"),
702
+ createdAt: timestamptz("created_at").notNull(),
703
+ updatedAt: timestamptz("updated_at").notNull()
704
+ },
705
+ (table) => [
706
+ check2(
707
+ "junior_snapshots_status_check",
708
+ sql6`${table.status} in ('building', 'failed', 'ready')`
709
+ ),
710
+ check2(
711
+ "junior_snapshots_build_phase_check",
712
+ sql6`${table.buildPhase} is null or ${table.buildPhase} in ('created', 'dependencies_installed', 'repositories_prepared')`
713
+ ),
714
+ check2(
715
+ "junior_snapshots_ready_fields_check",
716
+ sql6`${table.status} <> 'ready' or (${table.snapshotId} is not null and ${table.buildDurationMs} is not null and ${table.generatedAt} is not null)`
717
+ ),
718
+ check2(
719
+ "junior_snapshots_build_fields_check",
720
+ sql6`${table.status} = 'ready' or (${table.buildStartedAt} is not null and ${table.buildPhase} is not null)`
721
+ ),
722
+ check2(
723
+ "junior_snapshots_build_duration_check",
724
+ sql6`${table.buildDurationMs} is null or ${table.buildDurationMs} >= 0`
725
+ ),
726
+ // Provider snapshot ids are unique. Nulls stay allowed for in-flight rows.
727
+ uniqueIndex8("junior_snapshots_snapshot_id_uidx").on(table.snapshotId),
728
+ index13("junior_snapshots_workspace_idx").on(table.workspaceId),
729
+ index13("junior_snapshots_workspace_profile_status_idx").on(
730
+ table.workspaceId,
731
+ table.profileHash,
732
+ table.status
733
+ ),
734
+ index13("junior_snapshots_workspace_status_idx").on(
735
+ table.workspaceId,
736
+ table.status
737
+ )
738
+ ]
739
+ );
740
+
684
741
  // src/db/schema.ts
685
742
  var juniorSqlSchema = {
686
743
  juniorArtifacts,
@@ -697,6 +754,7 @@ var juniorSqlSchema = {
697
754
  juniorDestinations,
698
755
  juniorEventTasks,
699
756
  juniorIdentities,
757
+ juniorSnapshots,
700
758
  juniorStats,
701
759
  juniorTaskExecutions,
702
760
  juniorSchedulerRuns,
@@ -977,5 +1035,6 @@ export {
977
1035
  juniorSchedulerRuns,
978
1036
  juniorWorkspaces,
979
1037
  juniorWorkspaceRepos,
1038
+ juniorSnapshots,
980
1039
  createJuniorSqlExecutor
981
1040
  };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createAndEnqueueAgentInvocation
3
- } from "./chunk-IF3OK4XO.js";
3
+ } from "./chunk-TWIRPYVB.js";
4
4
  import {
5
5
  actorFromRun,
6
6
  toolInvocationDestination
@@ -5,7 +5,7 @@ import {
5
5
  logInfo,
6
6
  logWarn,
7
7
  setSpanAttributes
8
- } from "./chunk-5EPG7PYS.js";
8
+ } from "./chunk-IAOQPDO6.js";
9
9
  import {
10
10
  discoverInstalledPluginPackageContent,
11
11
  normalizePluginPackageNames
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  FUNCTION_TIMEOUT_BUFFER_SECONDS,
3
3
  getChatConfig
4
- } from "./chunk-E7HKIHI5.js";
4
+ } from "./chunk-CBPREIWS.js";
5
5
 
6
6
  // src/chat/runtime/request-deadline.ts
7
7
  import { AsyncLocalStorage } from "async_hooks";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  logWarn
3
- } from "./chunk-5EPG7PYS.js";
3
+ } from "./chunk-IAOQPDO6.js";
4
4
 
5
5
  // src/chat/conversation-privacy.ts
6
6
  import { AsyncLocalStorage } from "async_hooks";