@sentry/junior 0.1.1 → 0.3.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.
@@ -225,13 +225,21 @@ function emitSentry(level, body, attributes) {
225
225
  loggerFn(body, attributes);
226
226
  return;
227
227
  }
228
- Sentry.withScope((scope) => {
229
- for (const [key, value] of Object.entries(attributes)) {
230
- scope.setExtra(key, value);
231
- }
232
- const sentryLevel = level === "warn" ? "warning" : level;
233
- Sentry.captureMessage(body, sentryLevel);
234
- });
228
+ const sentryWithScope = sentry.withScope;
229
+ const sentryCaptureMessage = sentry.captureMessage;
230
+ const sentryLevel = level === "warn" ? "warning" : level;
231
+ if (typeof sentryWithScope === "function" && typeof sentryCaptureMessage === "function") {
232
+ sentryWithScope((scope) => {
233
+ for (const [key, value] of Object.entries(attributes)) {
234
+ scope.setExtra(key, value);
235
+ }
236
+ sentryCaptureMessage(body, sentryLevel);
237
+ });
238
+ return;
239
+ }
240
+ if (typeof sentryCaptureMessage === "function") {
241
+ sentryCaptureMessage(body, sentryLevel);
242
+ }
235
243
  }
236
244
  function formatConsoleLevel(level) {
237
245
  if (level === "debug") return "DBG";
@@ -353,12 +361,22 @@ var log = {
353
361
  "exception.message": normalizedError.message,
354
362
  "exception.stacktrace": normalizedError.stack
355
363
  }, body ?? normalizedError.message);
356
- Sentry.withScope((scope) => {
357
- for (const [key, value] of Object.entries(mergeAttributes(contextStorage.getStore(), attrs))) {
358
- scope.setExtra(key, value);
359
- }
360
- Sentry.captureException(normalizedError);
361
- });
364
+ let eventId;
365
+ const sentryWithScope = Sentry.withScope;
366
+ const sentryCaptureException = Sentry.captureException;
367
+ if (typeof sentryWithScope === "function" && typeof sentryCaptureException === "function") {
368
+ sentryWithScope((scope) => {
369
+ for (const [key, value] of Object.entries(mergeAttributes(contextStorage.getStore(), attrs))) {
370
+ scope.setExtra(key, value);
371
+ }
372
+ eventId = sentryCaptureException(normalizedError);
373
+ });
374
+ return eventId;
375
+ }
376
+ if (typeof sentryCaptureException === "function") {
377
+ eventId = sentryCaptureException(normalizedError);
378
+ }
379
+ return eventId;
362
380
  }
363
381
  };
364
382
  function withLogContext(context, callback) {
@@ -437,7 +455,7 @@ function logError(eventName, context = {}, attributes = {}, body) {
437
455
  }
438
456
  function logException(error, eventName, context = {}, attributes = {}, body) {
439
457
  const normalizedError = error instanceof Error ? error : new Error(String(error));
440
- log.exception(eventName, normalizedError, toContextAndAttributes(context, attributes), body);
458
+ return log.exception(eventName, normalizedError, toContextAndAttributes(context, attributes), body);
441
459
  }
442
460
  function setTags(context = {}) {
443
461
  setLogContext(context);
@@ -504,6 +522,34 @@ function setSpanStatus(status) {
504
522
  function toOptionalString(value) {
505
523
  return typeof value === "string" && value.trim() ? value : void 0;
506
524
  }
525
+ function getActiveTraceId() {
526
+ const sentry = Sentry2;
527
+ if (typeof sentry.getActiveSpan !== "function" || typeof sentry.spanToJSON !== "function") {
528
+ return void 0;
529
+ }
530
+ try {
531
+ const span = sentry.getActiveSpan();
532
+ if (!span) {
533
+ return void 0;
534
+ }
535
+ return toOptionalString(sentry.spanToJSON(span).trace_id);
536
+ } catch {
537
+ return void 0;
538
+ }
539
+ }
540
+ function resolveErrorReference(eventId) {
541
+ const traceId = getActiveTraceId();
542
+ if (!eventId && !traceId) {
543
+ return null;
544
+ }
545
+ if (!traceId) {
546
+ return null;
547
+ }
548
+ return {
549
+ traceId,
550
+ ...eventId ? { eventId } : {}
551
+ };
552
+ }
507
553
 
508
554
  export {
509
555
  logInfo,
@@ -516,5 +562,6 @@ export {
516
562
  withSpan,
517
563
  setSpanAttributes,
518
564
  setSpanStatus,
519
- toOptionalString
565
+ toOptionalString,
566
+ resolveErrorReference
520
567
  };
@@ -6,13 +6,13 @@ import {
6
6
  setSpanStatus,
7
7
  withContext,
8
8
  withSpan
9
- } from "./chunk-BBOVH5RF.js";
9
+ } from "./chunk-PY4AI2GZ.js";
10
10
 
11
11
  // src/handlers/webhooks.ts
12
12
  import { after } from "next/server";
13
13
  import * as Sentry from "@sentry/nextjs";
14
14
  async function loadBot() {
15
- const { bot } = await import("./bot-6KXJ366H.js");
15
+ const { bot } = await import("./bot-JSIREVQD.js");
16
16
  return bot;
17
17
  }
18
18
  async function POST(request, context) {
@@ -0,0 +1,328 @@
1
+ // src/chat/fs-utils.ts
2
+ import { statSync } from "fs";
3
+ function isDirectory(targetPath) {
4
+ try {
5
+ return statSync(targetPath).isDirectory();
6
+ } catch {
7
+ return false;
8
+ }
9
+ }
10
+ function isFile(targetPath) {
11
+ try {
12
+ return statSync(targetPath).isFile();
13
+ } catch {
14
+ return false;
15
+ }
16
+ }
17
+
18
+ // src/chat/discovery-roots.ts
19
+ import { readdirSync } from "fs";
20
+ import path from "path";
21
+ import { fileURLToPath } from "url";
22
+ function normalizePath(targetPath) {
23
+ return path.resolve(targetPath);
24
+ }
25
+ function uniqueResolvedPathsInOrder(values) {
26
+ const seen = /* @__PURE__ */ new Set();
27
+ const resolved = [];
28
+ for (const value of values) {
29
+ const normalized = normalizePath(value);
30
+ if (seen.has(normalized)) {
31
+ continue;
32
+ }
33
+ seen.add(normalized);
34
+ resolved.push(normalized);
35
+ }
36
+ return resolved;
37
+ }
38
+ function isNodeModulesPath(candidatePath) {
39
+ return path.basename(candidatePath) === "node_modules";
40
+ }
41
+ function isInsidePnpmStore(candidatePath) {
42
+ return candidatePath.split(path.sep).includes(".pnpm");
43
+ }
44
+ function runningFromInstalledPackage() {
45
+ const currentFile = fileURLToPath(import.meta.url);
46
+ const marker = `${path.sep}node_modules${path.sep}@sentry${path.sep}junior${path.sep}`;
47
+ return currentFile.includes(marker);
48
+ }
49
+ function listInstalledPackageNodeModulesDirs() {
50
+ if (!runningFromInstalledPackage()) {
51
+ return [];
52
+ }
53
+ const dirs = [];
54
+ let current = path.resolve(path.dirname(fileURLToPath(import.meta.url)));
55
+ while (true) {
56
+ if (isNodeModulesPath(current) && !isInsidePnpmStore(current) && isDirectory(current)) {
57
+ dirs.push(current);
58
+ }
59
+ const parent = path.dirname(current);
60
+ if (parent === current) {
61
+ break;
62
+ }
63
+ current = parent;
64
+ }
65
+ return dirs;
66
+ }
67
+ function listCwdAncestorNodeModulesDirs(cwd) {
68
+ const resolvedCwd = normalizePath(cwd);
69
+ const dirs = [];
70
+ let current = resolvedCwd;
71
+ while (true) {
72
+ const nodeModulesDir = path.join(current, "node_modules");
73
+ if (isDirectory(nodeModulesDir)) {
74
+ dirs.push(nodeModulesDir);
75
+ }
76
+ if (isFile(path.join(current, "package.json"))) {
77
+ break;
78
+ }
79
+ const parent = path.dirname(current);
80
+ if (parent === current) {
81
+ break;
82
+ }
83
+ current = parent;
84
+ }
85
+ return dirs;
86
+ }
87
+ function discoverNodeModulesDirs(cwd = process.cwd(), options) {
88
+ const explicit = options?.candidateDirs?.filter((dir) => isDirectory(dir)) ?? [];
89
+ if (explicit.length > 0) {
90
+ return uniqueResolvedPathsInOrder(explicit);
91
+ }
92
+ return uniqueResolvedPathsInOrder([
93
+ ...listInstalledPackageNodeModulesDirs(),
94
+ ...listCwdAncestorNodeModulesDirs(cwd)
95
+ ]);
96
+ }
97
+ function discoverProjectRoots(cwd = process.cwd(), options) {
98
+ const roots = discoverNodeModulesDirs(cwd, options?.nodeModulesDirs ? { candidateDirs: options.nodeModulesDirs } : void 0).map((nodeModulesDir) => path.dirname(nodeModulesDir));
99
+ return uniqueResolvedPathsInOrder([cwd, ...roots]);
100
+ }
101
+ function listTopLevelPackages(nodeModulesDir) {
102
+ const entries = readdirSync(nodeModulesDir, { withFileTypes: true }).filter((entry) => !entry.name.startsWith(".") && entry.name !== ".bin" && entry.name !== ".pnpm").sort((left, right) => left.name.localeCompare(right.name));
103
+ const packages = [];
104
+ for (const entry of entries) {
105
+ const entryPath = path.join(nodeModulesDir, entry.name);
106
+ if (entry.name.startsWith("@")) {
107
+ if (!isDirectory(entryPath)) {
108
+ continue;
109
+ }
110
+ const scopedEntries = readdirSync(entryPath, { withFileTypes: true }).sort(
111
+ (left, right) => left.name.localeCompare(right.name)
112
+ );
113
+ for (const scopedEntry of scopedEntries) {
114
+ const packageName = `${entry.name}/${scopedEntry.name}`;
115
+ const packagePath = path.join(entryPath, scopedEntry.name);
116
+ if (!isDirectory(packagePath)) {
117
+ continue;
118
+ }
119
+ packages.push({ name: packageName, dir: packagePath });
120
+ }
121
+ continue;
122
+ }
123
+ if (!isDirectory(entryPath)) {
124
+ continue;
125
+ }
126
+ packages.push({ name: entry.name, dir: entryPath });
127
+ }
128
+ return packages;
129
+ }
130
+
131
+ // src/chat/plugins/package-discovery.ts
132
+ import { createRequire } from "module";
133
+ import path2 from "path";
134
+ var require2 = createRequire(import.meta.url);
135
+ function normalizeForGlob(targetPath) {
136
+ return targetPath.split(path2.sep).join("/");
137
+ }
138
+ function uniqueStringsInOrder(values) {
139
+ const seen = /* @__PURE__ */ new Set();
140
+ const resolved = [];
141
+ for (const value of values) {
142
+ if (seen.has(value)) {
143
+ continue;
144
+ }
145
+ seen.add(value);
146
+ resolved.push(value);
147
+ }
148
+ return resolved;
149
+ }
150
+ function pathWithinCwd(cwd, targetPath) {
151
+ const relative = path2.relative(cwd, targetPath);
152
+ if (!relative || relative.startsWith("..") || path2.isAbsolute(relative)) {
153
+ return null;
154
+ }
155
+ return `./${normalizeForGlob(relative)}`;
156
+ }
157
+ function parseRuntimeConfiguredPackageNames(value) {
158
+ if (!Array.isArray(value)) {
159
+ return null;
160
+ }
161
+ const parsed = value.filter((entry) => typeof entry === "string" && entry.trim().length > 0);
162
+ return uniqueStringsInOrder(parsed.map((entry) => entry.trim()));
163
+ }
164
+ function readNextRuntimeConfiguredPackageNames() {
165
+ try {
166
+ const nextConfigModule = require2("next/config");
167
+ const getConfig = nextConfigModule.default;
168
+ if (typeof getConfig !== "function") {
169
+ return null;
170
+ }
171
+ const runtimeConfig = getConfig();
172
+ return parseRuntimeConfiguredPackageNames(runtimeConfig?.serverRuntimeConfig?.juniorPluginPackages) ?? [];
173
+ } catch {
174
+ return null;
175
+ }
176
+ }
177
+ function findContainingNodeModulesDir(targetPath) {
178
+ let current = path2.resolve(targetPath);
179
+ while (true) {
180
+ if (path2.basename(current) === "node_modules") {
181
+ return current;
182
+ }
183
+ const parent = path2.dirname(current);
184
+ if (parent === current) {
185
+ return null;
186
+ }
187
+ current = parent;
188
+ }
189
+ }
190
+ function resolvePackageDirFromName(packageName, candidateNodeModulesDirs) {
191
+ for (const nodeModulesDir of candidateNodeModulesDirs) {
192
+ const packageDir = path2.join(nodeModulesDir, ...packageName.split("/"));
193
+ if (isDirectory(packageDir)) {
194
+ return {
195
+ dir: path2.resolve(packageDir),
196
+ nodeModulesDir: path2.resolve(nodeModulesDir)
197
+ };
198
+ }
199
+ }
200
+ try {
201
+ const packageJsonPath = require2.resolve(`${packageName}/package.json`);
202
+ const dir = path2.dirname(packageJsonPath);
203
+ const nodeModulesDir = findContainingNodeModulesDir(dir);
204
+ if (!nodeModulesDir) {
205
+ return null;
206
+ }
207
+ return {
208
+ dir: path2.resolve(dir),
209
+ nodeModulesDir: path2.resolve(nodeModulesDir)
210
+ };
211
+ } catch {
212
+ return null;
213
+ }
214
+ }
215
+ function discoverDeclaredPackages(packageNames, candidateNodeModulesDirs) {
216
+ const discovered = [];
217
+ const seenPackageNames = /* @__PURE__ */ new Set();
218
+ const seenPackageDirs = /* @__PURE__ */ new Set();
219
+ for (const packageName of packageNames) {
220
+ const resolved = resolvePackageDirFromName(packageName, candidateNodeModulesDirs);
221
+ if (!resolved) {
222
+ continue;
223
+ }
224
+ if (seenPackageNames.has(packageName) || seenPackageDirs.has(resolved.dir)) {
225
+ continue;
226
+ }
227
+ const hasRootPluginManifest = isFile(path2.join(resolved.dir, "plugin.yaml"));
228
+ const hasPluginsDir = isDirectory(path2.join(resolved.dir, "plugins"));
229
+ const hasSkillsDir = isDirectory(path2.join(resolved.dir, "skills"));
230
+ if (!hasRootPluginManifest && !hasPluginsDir && !hasSkillsDir) {
231
+ continue;
232
+ }
233
+ seenPackageNames.add(packageName);
234
+ seenPackageDirs.add(resolved.dir);
235
+ discovered.push({
236
+ name: packageName,
237
+ dir: resolved.dir,
238
+ nodeModulesDir: resolved.nodeModulesDir,
239
+ hasRootPluginManifest,
240
+ hasPluginsDir,
241
+ hasSkillsDir
242
+ });
243
+ }
244
+ return discovered;
245
+ }
246
+ function discoverInstalledJuniorContentPackages(cwd = process.cwd(), nodeModulesDirs, packageNames) {
247
+ const resolvedCwd = path2.resolve(cwd);
248
+ const candidateNodeModulesDirs = nodeModulesDirs ?? discoverNodeModulesDirs(resolvedCwd);
249
+ const configuredPackageNames = packageNames ?? readNextRuntimeConfiguredPackageNames();
250
+ const declaredPackages = discoverDeclaredPackages(configuredPackageNames ?? [], candidateNodeModulesDirs);
251
+ const useFallbackScan = configuredPackageNames === null;
252
+ const discovered = [...declaredPackages];
253
+ const seenPackageNames = /* @__PURE__ */ new Set();
254
+ const seenPackageDirs = /* @__PURE__ */ new Set();
255
+ for (const pkg of declaredPackages) {
256
+ seenPackageNames.add(pkg.name);
257
+ seenPackageDirs.add(pkg.dir);
258
+ }
259
+ if (!useFallbackScan) {
260
+ return discovered;
261
+ }
262
+ for (const nodeModulesDir of candidateNodeModulesDirs) {
263
+ for (const pkg of listTopLevelPackages(nodeModulesDir)) {
264
+ const resolvedDir = path2.resolve(pkg.dir);
265
+ if (seenPackageNames.has(pkg.name) || seenPackageDirs.has(resolvedDir)) {
266
+ continue;
267
+ }
268
+ seenPackageNames.add(pkg.name);
269
+ seenPackageDirs.add(resolvedDir);
270
+ const hasRootPluginManifest = isFile(path2.join(resolvedDir, "plugin.yaml"));
271
+ const hasPluginsDir = isDirectory(path2.join(resolvedDir, "plugins"));
272
+ const hasSkillsDir = isDirectory(path2.join(resolvedDir, "skills"));
273
+ if (!hasRootPluginManifest && !hasPluginsDir && !hasSkillsDir) {
274
+ continue;
275
+ }
276
+ discovered.push({
277
+ name: pkg.name,
278
+ dir: resolvedDir,
279
+ nodeModulesDir: path2.resolve(nodeModulesDir),
280
+ hasRootPluginManifest,
281
+ hasPluginsDir,
282
+ hasSkillsDir
283
+ });
284
+ }
285
+ }
286
+ return discovered;
287
+ }
288
+ function discoverInstalledPluginPackageContent(cwd = process.cwd(), options) {
289
+ const resolvedCwd = path2.resolve(cwd);
290
+ const discoveredPackages = discoverInstalledJuniorContentPackages(resolvedCwd, options?.nodeModulesDirs, options?.packageNames);
291
+ const manifestRoots = [];
292
+ const skillRoots = [];
293
+ const tracingIncludes = [];
294
+ for (const pkg of discoveredPackages) {
295
+ const packagePathFromNodeModules = pathWithinCwd(resolvedCwd, path2.join(pkg.nodeModulesDir, ...pkg.name.split("/")));
296
+ if (pkg.hasRootPluginManifest) {
297
+ manifestRoots.push(pkg.dir);
298
+ if (packagePathFromNodeModules) {
299
+ tracingIncludes.push(`${packagePathFromNodeModules}/plugin.yaml`);
300
+ }
301
+ }
302
+ if (pkg.hasPluginsDir) {
303
+ manifestRoots.push(path2.join(pkg.dir, "plugins"));
304
+ if (packagePathFromNodeModules) {
305
+ tracingIncludes.push(`${packagePathFromNodeModules}/plugins/**/*`);
306
+ }
307
+ }
308
+ if (pkg.hasSkillsDir) {
309
+ skillRoots.push(path2.join(pkg.dir, "skills"));
310
+ if (packagePathFromNodeModules) {
311
+ tracingIncludes.push(`${packagePathFromNodeModules}/skills/**/*`);
312
+ }
313
+ }
314
+ }
315
+ return {
316
+ packageNames: uniqueStringsInOrder(discoveredPackages.map((pkg) => pkg.name)),
317
+ manifestRoots: uniqueStringsInOrder(manifestRoots),
318
+ skillRoots: uniqueStringsInOrder(skillRoots),
319
+ tracingIncludes: uniqueStringsInOrder(tracingIncludes)
320
+ };
321
+ }
322
+
323
+ export {
324
+ isDirectory,
325
+ discoverNodeModulesDirs,
326
+ discoverProjectRoots,
327
+ discoverInstalledPluginPackageContent
328
+ };
@@ -0,0 +1,3 @@
1
+ declare function runInit(dir: string, log?: (line: string) => void): Promise<void>;
2
+
3
+ export { runInit };
@@ -0,0 +1,105 @@
1
+ // src/cli/init.ts
2
+ import fs from "fs";
3
+ import path from "path";
4
+ function writeRouteModule(filePath, exportLine) {
5
+ fs.writeFileSync(filePath, `${exportLine}
6
+ export const runtime = "nodejs";
7
+ `);
8
+ }
9
+ function writeWrapperFiles(targetDir) {
10
+ const routeDir = path.join(targetDir, "app", "api", "[...path]");
11
+ fs.mkdirSync(routeDir, { recursive: true });
12
+ writeRouteModule(path.join(routeDir, "route.js"), 'export { GET, POST } from "@sentry/junior/handler";');
13
+ const queueRouteDir = path.join(targetDir, "app", "api", "queue", "callback");
14
+ fs.mkdirSync(queueRouteDir, { recursive: true });
15
+ writeRouteModule(
16
+ path.join(queueRouteDir, "route.js"),
17
+ 'export { POST } from "@sentry/junior/handlers/queue-callback";'
18
+ );
19
+ fs.mkdirSync(path.join(targetDir, "app"), { recursive: true });
20
+ fs.writeFileSync(
21
+ path.join(targetDir, "app", "layout.js"),
22
+ 'export { default } from "@sentry/junior/app/layout";\n'
23
+ );
24
+ fs.writeFileSync(
25
+ path.join(targetDir, "next.config.mjs"),
26
+ 'import { withJunior } from "@sentry/junior/config";\nexport default withJunior();\n'
27
+ );
28
+ fs.writeFileSync(
29
+ path.join(targetDir, "instrumentation.js"),
30
+ 'export { register, onRequestError } from "@sentry/junior/instrumentation";\n'
31
+ );
32
+ }
33
+ async function runInit(dir, log = console.log) {
34
+ const targetDir = dir.trim();
35
+ if (!targetDir) {
36
+ throw new Error("usage: junior init <dir>");
37
+ }
38
+ const target = path.resolve(targetDir);
39
+ if (fs.existsSync(target)) {
40
+ const stat = fs.statSync(target);
41
+ if (!stat.isDirectory()) {
42
+ throw new Error(`refusing to initialize non-directory path: ${target}`);
43
+ }
44
+ if (fs.readdirSync(target).length > 0) {
45
+ throw new Error(`refusing to initialize non-empty directory: ${target}`);
46
+ }
47
+ } else {
48
+ fs.mkdirSync(target, { recursive: true });
49
+ }
50
+ const name = path.basename(target);
51
+ const pkg = {
52
+ name,
53
+ version: "0.1.0",
54
+ private: true,
55
+ type: "module",
56
+ scripts: {
57
+ dev: "next dev",
58
+ build: "next build",
59
+ start: "next start"
60
+ },
61
+ dependencies: {
62
+ "@sentry/junior": "latest",
63
+ next: "^16.0.0",
64
+ react: "^19.0.0",
65
+ "react-dom": "^19.0.0",
66
+ "@sentry/nextjs": "^10.0.0"
67
+ }
68
+ };
69
+ fs.writeFileSync(path.join(target, "package.json"), `${JSON.stringify(pkg, null, 2)}
70
+ `);
71
+ const dataDir = path.join(target, "app", "data");
72
+ fs.mkdirSync(dataDir, { recursive: true });
73
+ fs.writeFileSync(path.join(dataDir, "SOUL.md"), `# ${name}
74
+
75
+ You are ${name}, a helpful assistant.
76
+ `);
77
+ const skillsDir = path.join(target, "app", "skills");
78
+ fs.mkdirSync(skillsDir, { recursive: true });
79
+ fs.writeFileSync(path.join(skillsDir, ".gitkeep"), "");
80
+ const pluginsDir = path.join(target, "app", "plugins");
81
+ fs.mkdirSync(pluginsDir, { recursive: true });
82
+ fs.writeFileSync(path.join(pluginsDir, ".gitkeep"), "");
83
+ fs.writeFileSync(path.join(target, ".gitignore"), ["node_modules/", ".next/", ".env", ".env.local", ""].join("\n"));
84
+ fs.writeFileSync(
85
+ path.join(target, ".env.example"),
86
+ [
87
+ "SLACK_BOT_TOKEN=",
88
+ "SLACK_SIGNING_SECRET=",
89
+ "JUNIOR_BOT_NAME=",
90
+ "AI_MODEL=",
91
+ "AI_FAST_MODEL=",
92
+ "REDIS_URL=",
93
+ "NEXT_PUBLIC_SENTRY_DSN=",
94
+ ""
95
+ ].join("\n")
96
+ );
97
+ writeWrapperFiles(target);
98
+ log(`Created ${name} at ${target}`);
99
+ log("");
100
+ log(` cd ${targetDir} && pnpm install && pnpm dev`);
101
+ log("");
102
+ }
103
+ export {
104
+ runInit
105
+ };
@@ -0,0 +1,11 @@
1
+ declare const CLI_USAGE = "usage: junior init <dir>\n junior snapshot create";
2
+ interface CliHandlers {
3
+ runInit: (dir: string) => Promise<void>;
4
+ runSnapshotCreate: () => Promise<void>;
5
+ }
6
+ interface CliIo {
7
+ error: (line: string) => void;
8
+ }
9
+ declare function runCli(argv: string[], handlers: CliHandlers, io?: CliIo): Promise<number>;
10
+
11
+ export { CLI_USAGE, runCli };
@@ -0,0 +1,30 @@
1
+ // src/cli/run.ts
2
+ var CLI_USAGE = "usage: junior init <dir>\n junior snapshot create";
3
+ var DEFAULT_IO = {
4
+ error: console.error
5
+ };
6
+ async function runCli(argv, handlers, io = DEFAULT_IO) {
7
+ const [command, subcommand, ...rest] = argv;
8
+ if (command === "init") {
9
+ if (!subcommand || rest.length > 0) {
10
+ io.error(CLI_USAGE);
11
+ return 1;
12
+ }
13
+ await handlers.runInit(subcommand);
14
+ return 0;
15
+ }
16
+ if (command === "snapshot" && subcommand === "create") {
17
+ if (rest.length > 0) {
18
+ io.error(CLI_USAGE);
19
+ return 1;
20
+ }
21
+ await handlers.runSnapshotCreate();
22
+ return 0;
23
+ }
24
+ io.error(CLI_USAGE);
25
+ return 1;
26
+ }
27
+ export {
28
+ CLI_USAGE,
29
+ runCli
30
+ };
@@ -0,0 +1,3 @@
1
+ declare function runSnapshotCreate(log?: (line: string) => void): Promise<void>;
2
+
3
+ export { runSnapshotCreate };
@@ -0,0 +1,58 @@
1
+ import {
2
+ disconnectStateAdapter,
3
+ resolveRuntimeDependencySnapshot
4
+ } from "../chunk-DPTR2FNH.js";
5
+ import "../chunk-PY4AI2GZ.js";
6
+ import "../chunk-SP6LV35L.js";
7
+
8
+ // src/cli/snapshot-warmup.ts
9
+ var DEFAULT_RUNTIME = "node22";
10
+ var DEFAULT_TIMEOUT_MS = 10 * 60 * 1e3;
11
+ function progressMessage(phase) {
12
+ if (phase === "resolve_start") {
13
+ return "Resolving sandbox snapshot profile...";
14
+ }
15
+ if (phase === "cache_hit") {
16
+ return "Using cached sandbox snapshot.";
17
+ }
18
+ if (phase === "waiting_for_lock") {
19
+ return "Waiting for sandbox snapshot build lock...";
20
+ }
21
+ if (phase === "building_snapshot") {
22
+ return "Building sandbox snapshot...";
23
+ }
24
+ return "Sandbox snapshot build complete.";
25
+ }
26
+ async function runSnapshotCreate(log = console.log) {
27
+ const runtime = DEFAULT_RUNTIME;
28
+ const timeoutMs = DEFAULT_TIMEOUT_MS;
29
+ try {
30
+ const emitted = /* @__PURE__ */ new Set();
31
+ const snapshot = await resolveRuntimeDependencySnapshot({
32
+ runtime,
33
+ timeoutMs,
34
+ onProgress: async (phase) => {
35
+ if (emitted.has(phase)) {
36
+ return;
37
+ }
38
+ emitted.add(phase);
39
+ log(progressMessage(phase));
40
+ }
41
+ });
42
+ const fields = [
43
+ `runtime=${runtime}`,
44
+ `resolve_outcome=${snapshot.resolveOutcome}`,
45
+ `cache_hit=${snapshot.cacheHit}`,
46
+ `dependency_count=${snapshot.dependencyCount}`,
47
+ ...snapshot.profileHash ? [`profile_hash=${snapshot.profileHash}`] : [],
48
+ ...snapshot.snapshotId ? [`snapshot_id=${snapshot.snapshotId}`] : [],
49
+ ...snapshot.rebuildReason ? [`rebuild_reason=${snapshot.rebuildReason}`] : []
50
+ ];
51
+ log(`Sandbox snapshot create complete: ${fields.join(" ")}`);
52
+ } finally {
53
+ await disconnectStateAdapter();
54
+ }
55
+ }
56
+ export {
57
+ runSnapshotCreate
58
+ };
@@ -1,3 +1,6 @@
1
+ /**
2
+ * Returns a minimal JSON health response for runtime health checks.
3
+ */
1
4
  declare function GET(): Promise<Response>;
2
5
 
3
6
  export { GET };
@@ -1,3 +1,10 @@
1
+ /**
2
+ * Handles `POST /api/queue/callback` for asynchronous thread processing.
3
+ *
4
+ * Keep this route as a dedicated handler in app code. The catch-all router can
5
+ * mirror this path for local/dev parity, but production queue delivery should
6
+ * always target the dedicated endpoint.
7
+ */
1
8
  declare function POST(request: Request): Promise<Response>;
2
9
 
3
10
  export { POST };