@sentry/junior 0.48.0 → 0.50.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.
@@ -7,7 +7,7 @@ import {
7
7
  serializeGenAiAttribute,
8
8
  setSpanAttributes,
9
9
  withSpan
10
- } from "./chunk-BCG3I2T2.js";
10
+ } from "./chunk-UKR24HLJ.js";
11
11
 
12
12
  // src/chat/state/adapter.ts
13
13
  import { createMemoryState } from "@chat-adapter/state-memory";
@@ -2,7 +2,7 @@ import {
2
2
  getPluginForSkillPath,
3
3
  getPluginSkillRoots,
4
4
  logWarn
5
- } from "./chunk-BCG3I2T2.js";
5
+ } from "./chunk-UKR24HLJ.js";
6
6
  import {
7
7
  skillRoots
8
8
  } from "./chunk-XPXD3FCE.js";
@@ -88,6 +88,9 @@ var skillFrontmatterSchema = z.object({
88
88
  }).optional(),
89
89
  "allowed-tools": z.string({
90
90
  error: 'Frontmatter field "allowed-tools" must be a string when present'
91
+ }).optional(),
92
+ "disable-model-invocation": z.boolean({
93
+ error: 'Frontmatter field "disable-model-invocation" must be a boolean when present'
91
94
  }).optional()
92
95
  }).passthrough();
93
96
  function stripFrontmatter(raw) {
@@ -113,7 +116,7 @@ function parseSkillFile(raw, expectedName) {
113
116
  if ("requires-capabilities" in parsed) {
114
117
  return {
115
118
  ok: false,
116
- error: 'Frontmatter field "requires-capabilities" is no longer supported; plugin-backed skills inherit credentials from their plugin.'
119
+ error: 'Frontmatter field "requires-capabilities" is no longer supported; provider credentials are declared by plugin.yaml.'
117
120
  };
118
121
  }
119
122
  if ("uses-config" in parsed) {
@@ -136,6 +139,7 @@ function parseSkillFile(raw, expectedName) {
136
139
  };
137
140
  }
138
141
  const allowedTools = parseTokenList(result.data["allowed-tools"]);
142
+ const disableModelInvocation = result.data["disable-model-invocation"] === true;
139
143
  return {
140
144
  ok: true,
141
145
  skill: {
@@ -145,7 +149,8 @@ function parseSkillFile(raw, expectedName) {
145
149
  ...result.data.metadata ? { metadata: result.data.metadata } : {},
146
150
  ...result.data.compatibility !== void 0 ? { compatibility: result.data.compatibility } : {},
147
151
  ...result.data.license !== void 0 ? { license: result.data.license } : {},
148
- ...allowedTools ? { allowedTools } : {}
152
+ ...allowedTools ? { allowedTools } : {},
153
+ ...disableModelInvocation ? { disableModelInvocation } : {}
149
154
  }
150
155
  };
151
156
  }
@@ -225,14 +230,15 @@ async function readSkillDirectory(skillDir) {
225
230
  );
226
231
  return null;
227
232
  }
228
- const { name, description, allowedTools } = parsed.skill;
233
+ const { name, description, allowedTools, disableModelInvocation } = parsed.skill;
229
234
  const plugin = getPluginForSkillPath(skillDir);
230
235
  return {
231
236
  name,
232
237
  description,
233
238
  skillPath: skillDir,
234
239
  ...plugin ? { pluginProvider: plugin.manifest.name } : {},
235
- ...allowedTools ? { allowedTools } : {}
240
+ ...allowedTools ? { allowedTools } : {},
241
+ ...disableModelInvocation ? { disableModelInvocation } : {}
236
242
  };
237
243
  } catch (error) {
238
244
  logWarn(
@@ -292,19 +298,39 @@ async function discoverSkills(options) {
292
298
  }
293
299
  function parseSkillInvocation(messageText, availableSkills) {
294
300
  const trimmed = messageText.trim();
295
- const match = /(?:^|\s)\/([a-z0-9]+(?:-[a-z0-9]+)*)(?:\s+([\s\S]*))?/i.exec(
296
- trimmed
297
- );
298
- if (!match) {
299
- return null;
301
+ const escapePattern = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
302
+ const slashMatch = /(?:^|\s)\/([a-z0-9]+(?:-[a-z0-9]+)*)(?:\s+([\s\S]*))?/i.exec(trimmed);
303
+ if (slashMatch) {
304
+ const skillName = slashMatch[1].toLowerCase();
305
+ if (!availableSkills.some((skill) => skill.name === skillName)) {
306
+ return null;
307
+ }
308
+ return {
309
+ skillName,
310
+ args: (slashMatch[2] ?? "").trim()
311
+ };
300
312
  }
301
- const skillName = match[1].toLowerCase();
302
- if (!availableSkills.some((skill) => skill.name === skillName)) {
313
+ const namedSkill = availableSkills.find((skill) => {
314
+ if (skill.disableModelInvocation !== true) {
315
+ return false;
316
+ }
317
+ const skillPattern = escapePattern(skill.name);
318
+ const explicitUse = new RegExp(
319
+ `\\b(?:use|run|load|call|invoke)\\s+(?:the\\s+)?${skillPattern}(?:\\s+skill)?\\b`,
320
+ "i"
321
+ );
322
+ const negatedUse = new RegExp(
323
+ `\\b(?:do\\s+not|don't|dont|never)\\s+(?:use|run|load|call|invoke)\\s+(?:the\\s+)?${skillPattern}(?:\\s+skill)?\\b`,
324
+ "i"
325
+ );
326
+ return explicitUse.test(trimmed) && !negatedUse.test(trimmed);
327
+ });
328
+ if (!namedSkill) {
303
329
  return null;
304
330
  }
305
331
  return {
306
- skillName,
307
- args: (match[2] ?? "").trim()
332
+ skillName: namedSkill.name,
333
+ args: trimmed
308
334
  };
309
335
  }
310
336
  function findSkillByName(skillName, available) {
@@ -329,7 +355,8 @@ async function loadSkillsByName(skillNames, available) {
329
355
  description: parsed.skill.description,
330
356
  skillPath: meta.skillPath,
331
357
  ...plugin ? { pluginProvider: plugin.manifest.name } : {},
332
- ...parsed.skill.allowedTools ? { allowedTools: parsed.skill.allowedTools } : {}
358
+ ...parsed.skill.allowedTools ? { allowedTools: parsed.skill.allowedTools } : {},
359
+ ...parsed.skill.disableModelInvocation ? { disableModelInvocation: parsed.skill.disableModelInvocation } : {}
333
360
  };
334
361
  skills.push({
335
362
  ...loadedMeta,
@@ -1463,6 +1463,130 @@ var manifestSourceSchema = z.object({
1463
1463
  error: "must be an object"
1464
1464
  }).optional()
1465
1465
  }).passthrough();
1466
+ function setDefined(target, key, value) {
1467
+ if (value !== void 0) {
1468
+ target[key] = value;
1469
+ }
1470
+ }
1471
+ function manifestConfigPatch(config) {
1472
+ const result = {};
1473
+ setDefined(result, "description", config.description);
1474
+ setDefined(result, "capabilities", config.capabilities);
1475
+ setDefined(result, "config-keys", config.configKeys);
1476
+ setDefined(result, "domains", config.domains);
1477
+ setDefined(result, "api-headers", config.apiHeaders);
1478
+ setDefined(result, "command-env", config.commandEnv);
1479
+ setDefined(result, "env-vars", config.envVars);
1480
+ if (config.credentials !== void 0) {
1481
+ if (!config.credentials) {
1482
+ result.credentials = null;
1483
+ } else {
1484
+ const credentials = {};
1485
+ setDefined(credentials, "type", config.credentials.type);
1486
+ setDefined(credentials, "domains", config.credentials.domains);
1487
+ setDefined(credentials, "api-headers", config.credentials.apiHeaders);
1488
+ setDefined(
1489
+ credentials,
1490
+ "auth-token-env",
1491
+ config.credentials.authTokenEnv
1492
+ );
1493
+ setDefined(
1494
+ credentials,
1495
+ "auth-token-placeholder",
1496
+ config.credentials.authTokenPlaceholder
1497
+ );
1498
+ setDefined(credentials, "app-id-env", config.credentials.appIdEnv);
1499
+ setDefined(
1500
+ credentials,
1501
+ "private-key-env",
1502
+ config.credentials.privateKeyEnv
1503
+ );
1504
+ setDefined(
1505
+ credentials,
1506
+ "installation-id-env",
1507
+ config.credentials.installationIdEnv
1508
+ );
1509
+ result.credentials = credentials;
1510
+ }
1511
+ }
1512
+ setDefined(result, "runtime-dependencies", config.runtimeDependencies);
1513
+ setDefined(result, "runtime-postinstall", config.runtimePostinstall);
1514
+ if (config.mcp !== void 0) {
1515
+ if (!config.mcp) {
1516
+ result.mcp = null;
1517
+ } else {
1518
+ const mcp = {};
1519
+ setDefined(mcp, "transport", config.mcp.transport);
1520
+ setDefined(mcp, "url", config.mcp.url);
1521
+ setDefined(mcp, "headers", config.mcp.headers);
1522
+ setDefined(mcp, "allowed-tools", config.mcp.allowedTools);
1523
+ result.mcp = mcp;
1524
+ }
1525
+ }
1526
+ if (config.oauth !== void 0) {
1527
+ if (!config.oauth) {
1528
+ result.oauth = null;
1529
+ } else {
1530
+ const oauth = {};
1531
+ setDefined(oauth, "client-id-env", config.oauth.clientIdEnv);
1532
+ setDefined(oauth, "client-secret-env", config.oauth.clientSecretEnv);
1533
+ setDefined(oauth, "authorize-endpoint", config.oauth.authorizeEndpoint);
1534
+ setDefined(oauth, "token-endpoint", config.oauth.tokenEndpoint);
1535
+ setDefined(oauth, "scope", config.oauth.scope);
1536
+ setDefined(oauth, "authorize-params", config.oauth.authorizeParams);
1537
+ setDefined(oauth, "token-auth-method", config.oauth.tokenAuthMethod);
1538
+ setDefined(oauth, "token-extra-headers", config.oauth.tokenExtraHeaders);
1539
+ result.oauth = oauth;
1540
+ }
1541
+ }
1542
+ if (config.target !== void 0) {
1543
+ if (!config.target) {
1544
+ result.target = null;
1545
+ } else {
1546
+ const target = {};
1547
+ setDefined(target, "type", config.target.type);
1548
+ setDefined(target, "config-key", config.target.configKey);
1549
+ setDefined(target, "command-flags", config.target.commandFlags);
1550
+ result.target = target;
1551
+ }
1552
+ }
1553
+ return result;
1554
+ }
1555
+ function isPlainRecord(value) {
1556
+ return Boolean(value && typeof value === "object" && !Array.isArray(value));
1557
+ }
1558
+ function mergeManifestConfig(base, patch, options = {}) {
1559
+ const merged = { ...base };
1560
+ for (const [key, value] of Object.entries(patch)) {
1561
+ if (options.root && key === "name") {
1562
+ throw new Error("plugins.manifests cannot change plugin names");
1563
+ }
1564
+ if (value === null) {
1565
+ delete merged[key];
1566
+ continue;
1567
+ }
1568
+ const current = merged[key];
1569
+ if (isPlainRecord(current) && isPlainRecord(value)) {
1570
+ merged[key] = mergeManifestConfig(current, value);
1571
+ continue;
1572
+ }
1573
+ merged[key] = value;
1574
+ }
1575
+ return merged;
1576
+ }
1577
+ function applyManifestConfig(source, config) {
1578
+ const name = source.name;
1579
+ if (typeof name !== "string") {
1580
+ return source;
1581
+ }
1582
+ const manifestConfig = config?.manifests?.[name];
1583
+ if (manifestConfig && "name" in manifestConfig) {
1584
+ throw new Error("plugins.manifests cannot change plugin names");
1585
+ }
1586
+ return manifestConfig ? mergeManifestConfig(source, manifestConfigPatch(manifestConfig), {
1587
+ root: true
1588
+ }) : source;
1589
+ }
1466
1590
  function formatPath(path3) {
1467
1591
  return path3.map((segment) => String(segment)).join(".");
1468
1592
  }
@@ -1835,7 +1959,7 @@ function normalizeMcp(data, envVars, name) {
1835
1959
  ...result.data["allowed-tools"] ? { allowedTools: result.data["allowed-tools"] } : {}
1836
1960
  };
1837
1961
  }
1838
- function parsePluginManifest(raw, dir) {
1962
+ function parsePluginManifest(raw, dir, config) {
1839
1963
  let parsedYaml;
1840
1964
  try {
1841
1965
  parsedYaml = parseYaml(raw);
@@ -1847,7 +1971,8 @@ function parsePluginManifest(raw, dir) {
1847
1971
  if (!parsedYaml || typeof parsedYaml !== "object" || Array.isArray(parsedYaml)) {
1848
1972
  throw new Error(`Invalid plugin manifest in ${dir}: expected an object`);
1849
1973
  }
1850
- const sourceResult = manifestSourceSchema.safeParse(parsedYaml);
1974
+ const source = applyManifestConfig(parsedYaml, config);
1975
+ const sourceResult = manifestSourceSchema.safeParse(source);
1851
1976
  if (!sourceResult.success) {
1852
1977
  const issue = sourceResult.error.issues[0];
1853
1978
  const path3 = formatPath(issue?.path ?? []);
@@ -2681,6 +2806,7 @@ function createOAuthBearerBroker(manifest, credentials, deps) {
2681
2806
 
2682
2807
  // src/chat/plugins/registry.ts
2683
2808
  var loadedPluginState;
2809
+ var pluginConfig;
2684
2810
  function getLoggedPluginNames() {
2685
2811
  const globalState = globalThis;
2686
2812
  globalState.__juniorLoggedPluginNames ??= /* @__PURE__ */ new Set();
@@ -2706,7 +2832,7 @@ function providerDomains(manifest) {
2706
2832
  ].sort((left, right) => left.localeCompare(right));
2707
2833
  }
2708
2834
  function registerPluginManifest(state, raw, pluginDir) {
2709
- const manifest = parsePluginManifest(raw, pluginDir);
2835
+ const manifest = parsePluginManifest(raw, pluginDir, pluginConfig);
2710
2836
  if (state.pluginsByName.has(manifest.name)) {
2711
2837
  throw new Error(`Duplicate plugin name "${manifest.name}"`);
2712
2838
  }
@@ -2721,7 +2847,7 @@ function registerPluginManifest(state, raw, pluginDir) {
2721
2847
  const owner = state.domainToPlugin.get(domain);
2722
2848
  if (owner) {
2723
2849
  throw new Error(
2724
- `Duplicate provider domain "${domain}" in plugin "${manifest.name}" already declared by plugin "${owner}"`
2850
+ `Duplicate provider domain "${domain}" in plugin "${manifest.name}" already declared by plugin "${owner}". Use plugins.manifests in PluginConfig to change one plugin's domains or credentials.`
2725
2851
  );
2726
2852
  }
2727
2853
  }
@@ -2793,7 +2919,8 @@ function getPluginCatalogSource() {
2793
2919
  signature: JSON.stringify({
2794
2920
  manifestRoots,
2795
2921
  packagedSkillRoots,
2796
- packageNames: [...packagedContent.packageNames].sort()
2922
+ packageNames: [...packagedContent.packageNames].sort(),
2923
+ pluginConfig: pluginConfig ?? {}
2797
2924
  })
2798
2925
  };
2799
2926
  }
@@ -2866,6 +2993,13 @@ function buildLoadedPluginState(source) {
2866
2993
  registerPluginManifest(state, raw, pluginDir);
2867
2994
  }
2868
2995
  }
2996
+ for (const name of Object.keys(pluginConfig?.manifests ?? {})) {
2997
+ if (!state.pluginsByName.has(name)) {
2998
+ throw new Error(
2999
+ `plugins.manifests.${name} does not match a loaded plugin`
3000
+ );
3001
+ }
3002
+ }
2869
3003
  return state;
2870
3004
  }
2871
3005
  function logLoadedPlugins(state) {
@@ -2902,6 +3036,9 @@ function ensurePluginsLoaded() {
2902
3036
  logLoadedPlugins(state);
2903
3037
  return state;
2904
3038
  }
3039
+ function setPluginConfig(config) {
3040
+ pluginConfig = config;
3041
+ }
2905
3042
  function getPluginCatalogSignature() {
2906
3043
  return ensurePluginsLoaded().signature;
2907
3044
  }
@@ -3069,6 +3206,7 @@ export {
3069
3206
  hasRequiredOAuthScope,
3070
3207
  buildOAuthTokenRequest,
3071
3208
  parseOAuthTokenResponse,
3209
+ setPluginConfig,
3072
3210
  getPluginCatalogSignature,
3073
3211
  getPluginCapabilityProviders,
3074
3212
  getPluginProviders,
package/dist/cli/check.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  parseSkillFile
3
- } from "../chunk-ZUUJTQ2H.js";
3
+ } from "../chunk-AYM42AN3.js";
4
4
  import {
5
5
  parsePluginManifest
6
- } from "../chunk-BCG3I2T2.js";
6
+ } from "../chunk-UKR24HLJ.js";
7
7
  import "../chunk-Z3YD6NHK.js";
8
8
  import "../chunk-XPXD3FCE.js";
9
9
  import "../chunk-2KG3PWR4.js";
@@ -383,6 +383,38 @@ function reportSkillGroup(label, skillResults, io) {
383
383
  function reportAppSkills(skillResults, io) {
384
384
  reportSkillGroup("app skills", skillResults, io);
385
385
  }
386
+ async function validateAppSourceFiles(rootDir, registeredConfigKeys) {
387
+ const errors = [];
388
+ const warnings = [];
389
+ for (const fileName of ["server.ts", "server.js", "nitro.config.ts"]) {
390
+ const sourcePath = path.join(rootDir, fileName);
391
+ let source;
392
+ try {
393
+ source = await fs.readFile(sourcePath, "utf8");
394
+ } catch {
395
+ continue;
396
+ }
397
+ if (/\bpluginPackages\s*:/.test(source)) {
398
+ errors.push(
399
+ `${sourcePath}: pluginPackages is no longer supported. Use plugins: { packages: [...] }.`
400
+ );
401
+ }
402
+ for (const defaultsBlock of source.matchAll(
403
+ /\bconfigDefaults\s*:\s*\{([\s\S]*?)\}/g
404
+ )) {
405
+ const block = defaultsBlock[1] ?? "";
406
+ for (const keyMatch of block.matchAll(/["']([^"']+)["']\s*:/g)) {
407
+ const key = keyMatch[1];
408
+ if (key && !registeredConfigKeys.has(key)) {
409
+ errors.push(
410
+ `${sourcePath}: configDefaults key "${key}" is not a registered plugin config key`
411
+ );
412
+ }
413
+ }
414
+ }
415
+ }
416
+ return { errors, warnings };
417
+ }
386
418
  async function validateAppFiles(appDir) {
387
419
  const errors = [];
388
420
  const warnings = [];
@@ -505,6 +537,15 @@ async function runCheck(rootDir = process.cwd(), io = DEFAULT_IO) {
505
537
  });
506
538
  errors.push(...result.errors);
507
539
  }
540
+ const registeredConfigKeys = new Set(
541
+ pluginResults.flatMap((result) => result.manifest?.configKeys ?? [])
542
+ );
543
+ const appSourceResult = await validateAppSourceFiles(
544
+ resolvedRoot,
545
+ registeredConfigKeys
546
+ );
547
+ warnings.push(...appSourceResult.warnings);
548
+ errors.push(...appSourceResult.errors);
508
549
  for (const skillDir of appAndLocalPluginSkillDirs) {
509
550
  const result = await validateSkillDirectory(skillDir, duplicateSkillNames);
510
551
  skillResultsByDir.set(skillDir, result);
package/dist/cli/init.js CHANGED
@@ -55,6 +55,36 @@ function writeVercelJson(targetDir) {
55
55
  `
56
56
  );
57
57
  }
58
+ function writeGitHubWorkflow(targetDir) {
59
+ const workflowDir = path.join(targetDir, ".github", "workflows");
60
+ fs.mkdirSync(workflowDir, { recursive: true });
61
+ fs.writeFileSync(
62
+ path.join(workflowDir, "ci.yml"),
63
+ `name: CI
64
+
65
+ on:
66
+ push:
67
+ branches: [main]
68
+ pull_request:
69
+
70
+ jobs:
71
+ build:
72
+ runs-on: ubuntu-latest
73
+ steps:
74
+ - uses: actions/checkout@v6
75
+ - uses: pnpm/action-setup@v6
76
+ with:
77
+ version: 10
78
+ - uses: actions/setup-node@v6
79
+ with:
80
+ node-version: 24
81
+ cache: pnpm
82
+ - run: pnpm install --frozen-lockfile
83
+ - run: pnpm check
84
+ - run: pnpm build
85
+ `
86
+ );
87
+ }
58
88
  async function runInit(dir, log = console.log) {
59
89
  const targetDir = dir.trim();
60
90
  if (!targetDir) {
@@ -155,6 +185,7 @@ SENTRY_ORG_SLUG=
155
185
  writeNitroConfig(target);
156
186
  writeViteConfig(target);
157
187
  writeVercelJson(target);
188
+ writeGitHubWorkflow(target);
158
189
  log(`Created ${name} at ${target}`);
159
190
  log("");
160
191
  log(` cd ${targetDir} && pnpm install && pnpm dev`);
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  disconnectStateAdapter,
3
3
  resolveRuntimeDependencySnapshot
4
- } from "../chunk-ELM6HJ6S.js";
4
+ } from "../chunk-AQ4RO2WA.js";
5
5
  import {
6
6
  getPluginProviders,
7
7
  getPluginRuntimeDependencies,
8
8
  getPluginRuntimePostinstall
9
- } from "../chunk-BCG3I2T2.js";
9
+ } from "../chunk-UKR24HLJ.js";
10
10
  import "../chunk-Z3YD6NHK.js";
11
11
  import "../chunk-XPXD3FCE.js";
12
12
  import "../chunk-2KG3PWR4.js";
package/dist/nitro.d.ts CHANGED
@@ -1,7 +1,10 @@
1
+ import { P as PluginConfig } from './types-X_iCClPb.js';
2
+
1
3
  interface JuniorNitroOptions {
2
4
  cwd?: string;
3
5
  maxDuration?: number;
4
- pluginPackages?: string[];
6
+ /** Plugin packages and manifest overrides bundled into the app. */
7
+ plugins?: PluginConfig;
5
8
  /**
6
9
  * Extra file patterns to copy into the server output for files that the
7
10
  * bundler cannot trace (e.g. dynamically imported providers).
package/dist/nitro.js CHANGED
@@ -46,10 +46,10 @@ function resolvePackageDir(pkgName) {
46
46
  }
47
47
 
48
48
  // src/build/copy-build-content.ts
49
- function copyAppAndPluginContent(cwd, serverRoot, pluginPackages) {
49
+ function copyAppAndPluginContent(cwd, serverRoot, packageNames) {
50
50
  copyIfExists(path2.join(cwd, "app"), path2.join(serverRoot, "app"));
51
51
  const packagedContent = discoverInstalledPluginPackageContent(cwd, {
52
- packageNames: pluginPackages
52
+ packageNames
53
53
  });
54
54
  for (const root of packagedContent.manifestRoots) {
55
55
  if (existsSync2(path2.join(root, "plugin.yaml"))) {
@@ -109,8 +109,8 @@ function copyRootIntoServerOutput(cwd, serverRoot, root) {
109
109
  }
110
110
 
111
111
  // src/build/virtual-config.ts
112
- function injectVirtualConfig(nitro, pluginPackages) {
113
- nitro.options.virtual["#junior/config"] = `export const pluginPackages = ${JSON.stringify(pluginPackages)};`;
112
+ function injectVirtualConfig(nitro, plugins) {
113
+ nitro.options.virtual["#junior/config"] = `export const plugins = ${JSON.stringify(plugins ?? { packages: [] })};`;
114
114
  }
115
115
 
116
116
  // src/nitro.ts
@@ -125,12 +125,12 @@ function juniorNitro(options = {}) {
125
125
  nitro.options.vercel.functions ??= {};
126
126
  nitro.options.vercel.functions.maxDuration ??= options.maxDuration ?? 800;
127
127
  applyRolldownTreeshakeWorkaround(nitro);
128
- injectVirtualConfig(nitro, options.pluginPackages ?? []);
128
+ injectVirtualConfig(nitro, options.plugins);
129
129
  nitro.hooks.hook("compiled", () => {
130
130
  copyAppAndPluginContent(
131
131
  cwd,
132
132
  nitro.options.output.serverDir,
133
- options.pluginPackages
133
+ options.plugins?.packages
134
134
  );
135
135
  copyIncludedFiles(
136
136
  nitro.options.output.serverDir,
@@ -0,0 +1,75 @@
1
+ interface PluginOAuthConfig {
2
+ clientIdEnv: string;
3
+ clientSecretEnv: string;
4
+ authorizeEndpoint: string;
5
+ tokenEndpoint: string;
6
+ scope?: string;
7
+ authorizeParams?: Record<string, string>;
8
+ tokenAuthMethod?: "body" | "basic";
9
+ tokenExtraHeaders?: Record<string, string>;
10
+ }
11
+ interface PluginRuntimePostinstallCommand {
12
+ cmd: string;
13
+ args?: string[];
14
+ sudo?: boolean;
15
+ }
16
+ interface PluginEnvVarDeclaration {
17
+ default?: string;
18
+ }
19
+ type PluginRuntimeDependencyConfig = {
20
+ type: "npm";
21
+ package: string;
22
+ version?: string;
23
+ } | {
24
+ type: "system";
25
+ package: string;
26
+ } | {
27
+ type: "system";
28
+ url: string;
29
+ sha256: string;
30
+ };
31
+ interface PluginOAuthConfigPatch extends Omit<Partial<PluginOAuthConfig>, "authorizeParams" | "tokenExtraHeaders"> {
32
+ authorizeParams?: Record<string, string | null> | null;
33
+ tokenExtraHeaders?: Record<string, string | null> | null;
34
+ }
35
+ /** Install-level changes applied to one plugin manifest before validation. */
36
+ interface PluginManifestConfig {
37
+ description?: string;
38
+ capabilities?: string[];
39
+ configKeys?: string[];
40
+ domains?: string[] | null;
41
+ apiHeaders?: Record<string, string | null> | null;
42
+ commandEnv?: Record<string, string | null> | null;
43
+ envVars?: Record<string, PluginEnvVarDeclaration | null> | null;
44
+ credentials?: {
45
+ type?: "oauth-bearer" | "github-app";
46
+ domains?: string[];
47
+ apiHeaders?: Record<string, string | null> | null;
48
+ authTokenEnv?: string;
49
+ authTokenPlaceholder?: string | null;
50
+ appIdEnv?: string;
51
+ privateKeyEnv?: string;
52
+ installationIdEnv?: string;
53
+ } | null;
54
+ runtimeDependencies?: PluginRuntimeDependencyConfig[] | null;
55
+ runtimePostinstall?: PluginRuntimePostinstallCommand[] | null;
56
+ mcp?: {
57
+ transport?: "http";
58
+ url?: string;
59
+ headers?: Record<string, string | null> | null;
60
+ allowedTools?: string[] | null;
61
+ } | null;
62
+ oauth?: PluginOAuthConfigPatch | null;
63
+ target?: {
64
+ type?: string;
65
+ configKey?: string;
66
+ commandFlags?: string[] | null;
67
+ } | null;
68
+ }
69
+ /** Install-level plugin package list and manifest configuration. */
70
+ interface PluginConfig {
71
+ packages?: string[];
72
+ manifests?: Record<string, PluginManifestConfig>;
73
+ }
74
+
75
+ export type { PluginConfig as P };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentry/junior",
3
- "version": "0.48.0",
3
+ "version": "0.50.0",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"