@sentry/junior 0.43.0 → 0.45.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.
@@ -563,6 +563,9 @@ function getVercelSandboxCredentials() {
563
563
  function createSandboxInstance(sandbox) {
564
564
  return {
565
565
  sandboxId: sandbox.name,
566
+ get sandboxEgressId() {
567
+ return sandbox.currentSession().sessionId;
568
+ },
566
569
  fs: sandbox.fs,
567
570
  extendTimeout(duration) {
568
571
  return sandbox.extendTimeout(duration);
package/dist/cli/check.js CHANGED
@@ -58,6 +58,81 @@ async function pathIsFile(targetPath) {
58
58
  return false;
59
59
  }
60
60
  }
61
+ async function readJsonFile(targetPath) {
62
+ try {
63
+ return JSON.parse(await fs.readFile(targetPath, "utf8"));
64
+ } catch {
65
+ return void 0;
66
+ }
67
+ }
68
+ async function readRootPackageJson(rootDir) {
69
+ return await readJsonFile(path.join(rootDir, "package.json"));
70
+ }
71
+ function packageInstallDir(rootDir, packageName) {
72
+ return path.join(rootDir, "node_modules", ...packageName.split("/"));
73
+ }
74
+ function declaredPackages(pkg) {
75
+ if (!pkg) {
76
+ return [];
77
+ }
78
+ const packages = /* @__PURE__ */ new Map();
79
+ for (const deps of [
80
+ pkg.dependencies,
81
+ pkg.optionalDependencies,
82
+ pkg.devDependencies
83
+ ]) {
84
+ for (const [name, spec] of Object.entries(deps ?? {})) {
85
+ if (!packages.has(name)) {
86
+ packages.set(name, spec);
87
+ }
88
+ }
89
+ }
90
+ return [...packages.entries()].map(([name, spec]) => ({ name, spec })).sort((left, right) => left.name.localeCompare(right.name));
91
+ }
92
+ async function readInstalledPackageVersion(rootDir, packageName) {
93
+ return (await readJsonFile(
94
+ path.join(packageInstallDir(rootDir, packageName), "package.json")
95
+ ))?.version;
96
+ }
97
+ async function packageHasPluginContent(rootDir, packageName) {
98
+ const packageDir = packageInstallDir(rootDir, packageName);
99
+ return await pathIsFile(path.join(packageDir, "plugin.yaml")) || await pathIsDirectory(path.join(packageDir, "plugins")) || await pathIsDirectory(path.join(packageDir, "skills"));
100
+ }
101
+ function comparableVersion(version) {
102
+ return version?.match(/\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?/)?.[0];
103
+ }
104
+ async function collectPackageWarnings(rootDir, packages) {
105
+ const warnings = [];
106
+ const packageSpecByName = new Map(
107
+ packages.map((declaredPackage) => [
108
+ declaredPackage.name,
109
+ declaredPackage.spec
110
+ ])
111
+ );
112
+ const coreVersion = comparableVersion(
113
+ await readInstalledPackageVersion(rootDir, "@sentry/junior") ?? packageSpecByName.get("@sentry/junior")
114
+ );
115
+ if (!coreVersion) {
116
+ return warnings;
117
+ }
118
+ for (const declaredPackage of packages) {
119
+ if (!declaredPackage.name.startsWith("@sentry/junior-")) {
120
+ continue;
121
+ }
122
+ if (!await packageHasPluginContent(rootDir, declaredPackage.name)) {
123
+ continue;
124
+ }
125
+ const pluginVersion = comparableVersion(
126
+ await readInstalledPackageVersion(rootDir, declaredPackage.name) ?? declaredPackage.spec
127
+ );
128
+ if (pluginVersion && pluginVersion !== coreVersion) {
129
+ warnings.push(
130
+ `${path.join(rootDir, "package.json")}: ${declaredPackage.name} version ${pluginVersion} does not match @sentry/junior version ${coreVersion}`
131
+ );
132
+ }
133
+ }
134
+ return warnings;
135
+ }
61
136
  async function validateSkillDirectory(skillDir, duplicateNames) {
62
137
  const skillFile = path.join(skillDir, "SKILL.md");
63
138
  const errors = [];
@@ -159,6 +234,63 @@ async function collectPluginDirectories(rootDir) {
159
234
  }
160
235
  return pluginDirs.sort((left, right) => left.localeCompare(right));
161
236
  }
237
+ async function collectPackagedContent(rootDir, packages) {
238
+ const pluginDirs = [];
239
+ const skillRoots = [];
240
+ for (const declaredPackage of packages) {
241
+ const packageDir = packageInstallDir(rootDir, declaredPackage.name);
242
+ if (!await pathIsDirectory(packageDir)) {
243
+ continue;
244
+ }
245
+ const rootManifestPath = path.join(packageDir, "plugin.yaml");
246
+ const hasRootManifest = await pathIsFile(rootManifestPath);
247
+ const packageSkillsRoot = path.join(packageDir, "skills");
248
+ if (hasRootManifest) {
249
+ pluginDirs.push({
250
+ pluginDir: packageDir,
251
+ packageName: declaredPackage.name
252
+ });
253
+ } else if (await pathIsDirectory(packageSkillsRoot)) {
254
+ skillRoots.push({
255
+ root: packageSkillsRoot,
256
+ packageName: declaredPackage.name
257
+ });
258
+ }
259
+ const nestedPluginsRoot = path.join(packageDir, "plugins");
260
+ let nestedEntries;
261
+ try {
262
+ nestedEntries = await fs.readdir(nestedPluginsRoot, {
263
+ withFileTypes: true
264
+ });
265
+ } catch {
266
+ continue;
267
+ }
268
+ for (const entry of nestedEntries) {
269
+ if (!entry.isDirectory()) {
270
+ continue;
271
+ }
272
+ const pluginDir = path.join(nestedPluginsRoot, entry.name);
273
+ if (await pathIsFile(path.join(pluginDir, "plugin.yaml"))) {
274
+ pluginDirs.push({
275
+ pluginDir,
276
+ packageName: declaredPackage.name
277
+ });
278
+ }
279
+ }
280
+ }
281
+ return {
282
+ pluginDirs: pluginDirs.sort(
283
+ (left, right) => `${left.packageName}:${left.pluginDir}`.localeCompare(
284
+ `${right.packageName}:${right.pluginDir}`
285
+ )
286
+ ),
287
+ skillRoots: skillRoots.sort(
288
+ (left, right) => `${left.packageName}:${left.root}`.localeCompare(
289
+ `${right.packageName}:${right.root}`
290
+ )
291
+ )
292
+ };
293
+ }
162
294
  async function collectSkillDirectories(root) {
163
295
  const skillDirs = [];
164
296
  let entries;
@@ -222,7 +354,8 @@ function reportPluginResult(result, io) {
222
354
  skillWarningCount
223
355
  );
224
356
  const pluginName = result.manifest?.name ?? path.basename(result.pluginDir);
225
- io.info(formatHeading(status, `plugin ${pluginName}`));
357
+ const label = result.packageName ? `packaged plugin ${pluginName} (${result.packageName})` : `plugin ${pluginName}`;
358
+ io.info(formatHeading(status, label));
226
359
  for (const [index, skillResult] of result.skillResults.entries()) {
227
360
  reportSkillResult(
228
361
  skillResult,
@@ -232,7 +365,7 @@ function reportPluginResult(result, io) {
232
365
  );
233
366
  }
234
367
  }
235
- function reportAppSkills(skillResults, io) {
368
+ function reportSkillGroup(label, skillResults, io) {
236
369
  const errorCount = skillResults.reduce(
237
370
  (count, skillResult) => count + skillResult.errors.length,
238
371
  0
@@ -242,11 +375,14 @@ function reportAppSkills(skillResults, io) {
242
375
  0
243
376
  );
244
377
  const status = formatStatus(errorCount, warningCount);
245
- io.info(formatHeading(status, "app skills"));
378
+ io.info(formatHeading(status, label));
246
379
  for (const [index, skillResult] of skillResults.entries()) {
247
380
  reportSkillResult(skillResult, io, " ", index === skillResults.length - 1);
248
381
  }
249
382
  }
383
+ function reportAppSkills(skillResults, io) {
384
+ reportSkillGroup("app skills", skillResults, io);
385
+ }
250
386
  async function validateAppFiles(appDir) {
251
387
  const errors = [];
252
388
  const warnings = [];
@@ -293,52 +429,111 @@ async function runCheck(rootDir = process.cwd(), io = DEFAULT_IO) {
293
429
  `validation root does not exist or is not a directory: ${resolvedRoot}`
294
430
  );
295
431
  }
296
- const pluginDirs = await collectPluginDirectories(resolvedRoot);
432
+ const rootPackageJson = await readRootPackageJson(resolvedRoot);
433
+ const packages = declaredPackages(rootPackageJson);
434
+ const packageWarnings = await collectPackageWarnings(resolvedRoot, packages);
435
+ const packagedContent = await collectPackagedContent(resolvedRoot, packages);
436
+ const appPluginDirs = await collectPluginDirectories(resolvedRoot);
437
+ const packagedPluginDirs = packagedContent.pluginDirs;
438
+ const pluginDirs = [
439
+ ...appPluginDirs.map((pluginDir) => ({
440
+ pluginDir,
441
+ packageName: void 0
442
+ })),
443
+ ...packagedPluginDirs
444
+ ];
297
445
  const appSkillsRoot = contentRoot(resolvedRoot, "skills");
298
446
  const appSkillDirs = await collectSkillDirectories(appSkillsRoot);
299
447
  const pluginSkillDirs = /* @__PURE__ */ new Map();
300
- for (const pluginDir of pluginDirs) {
448
+ for (const { pluginDir } of pluginDirs) {
301
449
  pluginSkillDirs.set(
302
450
  pluginDir,
303
451
  await collectSkillDirectories(path.join(pluginDir, "skills"))
304
452
  );
305
453
  }
306
- const skillDirs = [
454
+ const packagedSkillDirsByPackage = /* @__PURE__ */ new Map();
455
+ for (const skillRoot of packagedContent.skillRoots) {
456
+ packagedSkillDirsByPackage.set(
457
+ skillRoot.packageName,
458
+ await collectSkillDirectories(skillRoot.root)
459
+ );
460
+ }
461
+ const packagedStandaloneSkillDirs = [
462
+ ...packagedSkillDirsByPackage.values()
463
+ ].flat();
464
+ const appAndLocalPluginSkillDirs = [
307
465
  ...appSkillDirs,
308
- ...pluginDirs.flatMap((pluginDir) => pluginSkillDirs.get(pluginDir) ?? [])
466
+ ...appPluginDirs.flatMap(
467
+ (pluginDir) => pluginSkillDirs.get(pluginDir) ?? []
468
+ )
309
469
  ].sort((left, right) => left.localeCompare(right));
470
+ const packagedSkillDirs = [
471
+ ...packagedPluginDirs.flatMap(
472
+ ({ pluginDir }) => pluginSkillDirs.get(pluginDir) ?? []
473
+ ),
474
+ ...packagedStandaloneSkillDirs
475
+ ].sort((left, right) => left.localeCompare(right));
476
+ const skillDirs = [...appAndLocalPluginSkillDirs, ...packagedSkillDirs].sort(
477
+ (left, right) => left.localeCompare(right)
478
+ );
310
479
  const duplicateSkillNames = /* @__PURE__ */ new Map();
311
480
  const duplicatePluginNames = /* @__PURE__ */ new Map();
312
481
  const duplicateProviderDomains = /* @__PURE__ */ new Map();
482
+ const duplicatePackagedSkillNames = /* @__PURE__ */ new Map();
483
+ const duplicatePackagedPluginNames = /* @__PURE__ */ new Map();
484
+ const duplicatePackagedProviderDomains = /* @__PURE__ */ new Map();
313
485
  const warnings = [];
314
486
  const errors = [];
315
487
  const pluginResults = [];
316
488
  const skillResultsByDir = /* @__PURE__ */ new Map();
317
- for (const pluginDir of pluginDirs) {
489
+ warnings.push(...packageWarnings);
490
+ for (const { pluginDir, packageName } of pluginDirs) {
491
+ const pluginNameMap = packageName ? duplicatePackagedPluginNames : duplicatePluginNames;
492
+ const providerDomainMap = packageName ? duplicatePackagedProviderDomains : duplicateProviderDomains;
318
493
  const result = await validatePluginDirectory(
319
494
  pluginDir,
320
- duplicatePluginNames,
321
- duplicateProviderDomains
495
+ pluginNameMap,
496
+ providerDomainMap
322
497
  );
323
498
  pluginResults.push({
324
499
  pluginDir,
325
500
  manifestPath: result.manifestPath,
501
+ ...packageName ? { packageName } : {},
326
502
  ...result.manifest ? { manifest: result.manifest } : {},
327
503
  errors: result.errors,
328
504
  skillResults: []
329
505
  });
330
506
  errors.push(...result.errors);
331
507
  }
332
- for (const skillDir of skillDirs) {
508
+ for (const skillDir of appAndLocalPluginSkillDirs) {
333
509
  const result = await validateSkillDirectory(skillDir, duplicateSkillNames);
334
510
  skillResultsByDir.set(skillDir, result);
335
511
  warnings.push(...result.warnings);
336
512
  errors.push(...result.errors);
337
513
  }
514
+ for (const skillDir of packagedSkillDirs) {
515
+ const result = await validateSkillDirectory(
516
+ skillDir,
517
+ duplicatePackagedSkillNames
518
+ );
519
+ skillResultsByDir.set(skillDir, result);
520
+ warnings.push(...result.warnings);
521
+ errors.push(...result.errors);
522
+ }
338
523
  for (const pluginResult of pluginResults) {
339
524
  pluginResult.skillResults = (pluginSkillDirs.get(pluginResult.pluginDir) ?? []).map((skillDir) => skillResultsByDir.get(skillDir)).filter((result) => Boolean(result));
340
525
  }
341
526
  const appSkillResults = appSkillDirs.map((skillDir) => skillResultsByDir.get(skillDir)).filter((result) => Boolean(result));
527
+ const packagedStandaloneSkillResultsByPackage = /* @__PURE__ */ new Map();
528
+ for (const [packageName, packageSkillDirs] of packagedSkillDirsByPackage) {
529
+ const packageSkillResults = packageSkillDirs.map((skillDir) => skillResultsByDir.get(skillDir)).filter((result) => Boolean(result));
530
+ if (packageSkillResults.length > 0) {
531
+ packagedStandaloneSkillResultsByPackage.set(
532
+ packageName,
533
+ packageSkillResults
534
+ );
535
+ }
536
+ }
342
537
  const appDir = path.resolve(resolvedRoot, "app");
343
538
  let appFileResult = {
344
539
  errors: [],
@@ -366,6 +561,16 @@ async function runCheck(rootDir = process.cwd(), io = DEFAULT_IO) {
366
561
  for (const pluginResult of pluginResults) {
367
562
  reportPluginResult(pluginResult, io);
368
563
  }
564
+ for (const [
565
+ packageName,
566
+ packageSkillResults
567
+ ] of packagedStandaloneSkillResultsByPackage) {
568
+ reportSkillGroup(
569
+ `packaged skills (${packageName})`,
570
+ packageSkillResults,
571
+ io
572
+ );
573
+ }
369
574
  if (appSkillResults.length > 0) {
370
575
  reportAppSkills(appSkillResults, io);
371
576
  }
package/dist/cli/init.js CHANGED
@@ -80,6 +80,7 @@ async function runInit(dir, log = console.log) {
80
80
  type: "module",
81
81
  scripts: {
82
82
  dev: "vite dev",
83
+ check: "junior check",
83
84
  build: "junior snapshot create && vite build"
84
85
  },
85
86
  dependencies: {
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  disconnectStateAdapter,
3
3
  resolveRuntimeDependencySnapshot
4
- } from "../chunk-YSXHRIWR.js";
4
+ } from "../chunk-QAMTCT2R.js";
5
5
  import {
6
6
  getPluginProviders,
7
7
  getPluginRuntimeDependencies,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentry/junior",
3
- "version": "0.43.0",
3
+ "version": "0.45.0",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -21,9 +21,9 @@
21
21
  ],
22
22
  "dependencies": {
23
23
  "@ai-sdk/gateway": "^3.0.110",
24
- "@chat-adapter/slack": "4.27.0",
25
- "@chat-adapter/state-memory": "4.27.0",
26
- "@chat-adapter/state-redis": "4.27.0",
24
+ "@chat-adapter/slack": "4.28.1",
25
+ "@chat-adapter/state-memory": "4.28.1",
26
+ "@chat-adapter/state-redis": "4.28.1",
27
27
  "@logtape/logtape": "^2.0.7",
28
28
  "@mariozechner/pi-agent-core": "0.73.0",
29
29
  "@mariozechner/pi-ai": "0.73.0",
@@ -34,7 +34,7 @@
34
34
  "@vercel/sandbox": "2.0.0-beta.19",
35
35
  "ai": "^6.0.175",
36
36
  "bash-tool": "^1.3.16",
37
- "chat": "4.27.0",
37
+ "chat": "4.28.1",
38
38
  "hono": "^4.12.6",
39
39
  "just-bash": "2.14.2",
40
40
  "jose": "^6.2.2",