@sentry/junior 0.24.1 → 0.25.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.
- package/dist/app.js +843 -832
- package/dist/{chunk-RMVXZMXQ.js → chunk-A75TWGF2.js} +1 -1
- package/dist/{chunk-O5N42P7K.js → chunk-ICIRAL6Y.js} +9 -52
- package/dist/{chunk-I3WA75AD.js → chunk-RZJDO55D.js} +136 -172
- package/dist/cli/check.js +2 -2
- package/dist/cli/snapshot-warmup.js +2 -2
- package/package.json +1 -1
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
getPluginSkillRoots,
|
|
6
6
|
logInfo,
|
|
7
7
|
logWarn
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-RZJDO55D.js";
|
|
9
9
|
import {
|
|
10
10
|
skillRoots
|
|
11
11
|
} from "./chunk-XPXD3FCE.js";
|
|
@@ -18,19 +18,6 @@ import { parse as parseYaml } from "yaml";
|
|
|
18
18
|
|
|
19
19
|
// src/chat/capabilities/catalog.ts
|
|
20
20
|
var cachedCatalog;
|
|
21
|
-
function cloneProviderDefinition(provider) {
|
|
22
|
-
return {
|
|
23
|
-
...provider,
|
|
24
|
-
capabilities: [...provider.capabilities],
|
|
25
|
-
configKeys: [...provider.configKeys],
|
|
26
|
-
...provider.target ? {
|
|
27
|
-
target: {
|
|
28
|
-
...provider.target,
|
|
29
|
-
...provider.target.commandFlags ? { commandFlags: [...provider.target.commandFlags] } : {}
|
|
30
|
-
}
|
|
31
|
-
} : {}
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
21
|
function getCapabilityCatalog() {
|
|
35
22
|
const signature = getPluginCatalogSignature();
|
|
36
23
|
if (cachedCatalog?.signature === signature) return cachedCatalog;
|
|
@@ -53,19 +40,9 @@ function getCapabilityCatalog() {
|
|
|
53
40
|
cachedCatalog = { signature, providers, capabilityToProvider, configKeys };
|
|
54
41
|
return cachedCatalog;
|
|
55
42
|
}
|
|
56
|
-
function getCapabilityProvider(capability) {
|
|
57
|
-
const provider = getCapabilityCatalog().capabilityToProvider.get(capability);
|
|
58
|
-
return provider ? cloneProviderDefinition(provider) : void 0;
|
|
59
|
-
}
|
|
60
|
-
function isKnownCapability(capability) {
|
|
61
|
-
return getCapabilityCatalog().capabilityToProvider.has(capability);
|
|
62
|
-
}
|
|
63
43
|
function isKnownConfigKey(key) {
|
|
64
44
|
return getCapabilityCatalog().configKeys.has(key);
|
|
65
45
|
}
|
|
66
|
-
function listCapabilityProviders() {
|
|
67
|
-
return getCapabilityCatalog().providers.map(cloneProviderDefinition);
|
|
68
|
-
}
|
|
69
46
|
var catalogLogged = false;
|
|
70
47
|
function logCapabilityCatalogLoadedOnce() {
|
|
71
48
|
if (catalogLogged) return;
|
|
@@ -184,10 +161,6 @@ var skillFrontmatterSchema = z.object({
|
|
|
184
161
|
"allowed-tools": z.string({
|
|
185
162
|
error: 'Frontmatter field "allowed-tools" must be a string when present'
|
|
186
163
|
}).optional(),
|
|
187
|
-
"requires-capabilities": createTokenFieldSchema(
|
|
188
|
-
"requires-capabilities",
|
|
189
|
-
"provider.scope.write"
|
|
190
|
-
).optional(),
|
|
191
164
|
"uses-config": createTokenFieldSchema(
|
|
192
165
|
"uses-config",
|
|
193
166
|
"provider.repo"
|
|
@@ -213,6 +186,12 @@ function parseSkillFile(raw, expectedName) {
|
|
|
213
186
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
214
187
|
return { ok: false, error: "Frontmatter must be a YAML object" };
|
|
215
188
|
}
|
|
189
|
+
if ("requires-capabilities" in parsed) {
|
|
190
|
+
return {
|
|
191
|
+
ok: false,
|
|
192
|
+
error: 'Frontmatter field "requires-capabilities" is no longer supported; plugin-backed skills inherit credentials from their plugin.'
|
|
193
|
+
};
|
|
194
|
+
}
|
|
216
195
|
const result = skillFrontmatterSchema.safeParse(parsed);
|
|
217
196
|
if (!result.success) {
|
|
218
197
|
return {
|
|
@@ -227,9 +206,6 @@ function parseSkillFile(raw, expectedName) {
|
|
|
227
206
|
};
|
|
228
207
|
}
|
|
229
208
|
const allowedTools = parseTokenList(result.data["allowed-tools"]);
|
|
230
|
-
const requiresCapabilities = parseTokenList(
|
|
231
|
-
result.data["requires-capabilities"]
|
|
232
|
-
);
|
|
233
209
|
const usesConfig = parseTokenList(result.data["uses-config"]);
|
|
234
210
|
return {
|
|
235
211
|
ok: true,
|
|
@@ -241,7 +217,6 @@ function parseSkillFile(raw, expectedName) {
|
|
|
241
217
|
...result.data.compatibility !== void 0 ? { compatibility: result.data.compatibility } : {},
|
|
242
218
|
...result.data.license !== void 0 ? { license: result.data.license } : {},
|
|
243
219
|
...allowedTools ? { allowedTools } : {},
|
|
244
|
-
...requiresCapabilities ? { requiresCapabilities } : {},
|
|
245
220
|
...usesConfig ? { usesConfig } : {}
|
|
246
221
|
}
|
|
247
222
|
};
|
|
@@ -271,12 +246,6 @@ function resolveSkillRoots(options) {
|
|
|
271
246
|
return resolved;
|
|
272
247
|
}
|
|
273
248
|
function validateSkillMetadata(input) {
|
|
274
|
-
const unknownCapabilities = (input.requiresCapabilities ?? []).filter(
|
|
275
|
-
(capability) => !isKnownCapability(capability)
|
|
276
|
-
);
|
|
277
|
-
if (unknownCapabilities.length > 0) {
|
|
278
|
-
return `Unknown requires-capabilities values: ${unknownCapabilities.join(", ")}`;
|
|
279
|
-
}
|
|
280
249
|
const unknownConfigKeys = (input.usesConfig ?? []).filter(
|
|
281
250
|
(configKey) => !isKnownConfigKey(configKey)
|
|
282
251
|
);
|
|
@@ -302,18 +271,9 @@ async function readSkillDirectory(skillDir) {
|
|
|
302
271
|
);
|
|
303
272
|
return null;
|
|
304
273
|
}
|
|
305
|
-
const {
|
|
306
|
-
name,
|
|
307
|
-
description,
|
|
308
|
-
allowedTools,
|
|
309
|
-
requiresCapabilities,
|
|
310
|
-
usesConfig
|
|
311
|
-
} = parsed.skill;
|
|
274
|
+
const { name, description, allowedTools, usesConfig } = parsed.skill;
|
|
312
275
|
const plugin = getPluginForSkillPath(skillDir);
|
|
313
|
-
const metadataError = validateSkillMetadata({
|
|
314
|
-
requiresCapabilities,
|
|
315
|
-
usesConfig
|
|
316
|
-
});
|
|
276
|
+
const metadataError = validateSkillMetadata({ usesConfig });
|
|
317
277
|
if (metadataError) {
|
|
318
278
|
logWarn(
|
|
319
279
|
"skill_frontmatter_invalid",
|
|
@@ -332,7 +292,6 @@ async function readSkillDirectory(skillDir) {
|
|
|
332
292
|
skillPath: skillDir,
|
|
333
293
|
...plugin ? { pluginProvider: plugin.manifest.name } : {},
|
|
334
294
|
allowedTools,
|
|
335
|
-
requiresCapabilities,
|
|
336
295
|
usesConfig
|
|
337
296
|
};
|
|
338
297
|
} catch (error) {
|
|
@@ -433,8 +392,6 @@ async function loadSkillsByName(skillNames, available) {
|
|
|
433
392
|
}
|
|
434
393
|
|
|
435
394
|
export {
|
|
436
|
-
getCapabilityProvider,
|
|
437
|
-
listCapabilityProviders,
|
|
438
395
|
logCapabilityCatalogLoadedOnce,
|
|
439
396
|
parseSkillFile,
|
|
440
397
|
discoverSkills,
|
|
@@ -1195,84 +1195,39 @@ function toFiniteTokenCount(value) {
|
|
|
1195
1195
|
const rounded = Math.floor(value);
|
|
1196
1196
|
return rounded >= 0 ? rounded : void 0;
|
|
1197
1197
|
}
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
if (!sourceRecord) {
|
|
1210
|
-
return [];
|
|
1211
|
-
}
|
|
1212
|
-
const roots = [sourceRecord];
|
|
1213
|
-
const usage = asRecord(sourceRecord.usage);
|
|
1214
|
-
if (usage) {
|
|
1215
|
-
roots.push(usage);
|
|
1216
|
-
}
|
|
1217
|
-
const tokenUsage = asRecord(sourceRecord.tokenUsage);
|
|
1218
|
-
if (tokenUsage) {
|
|
1219
|
-
roots.push(tokenUsage);
|
|
1220
|
-
}
|
|
1221
|
-
const providerMetadata = asRecord(sourceRecord.providerMetadata);
|
|
1222
|
-
if (providerMetadata) {
|
|
1223
|
-
roots.push(providerMetadata);
|
|
1224
|
-
const providerUsage = asRecord(providerMetadata.usage);
|
|
1225
|
-
if (providerUsage) {
|
|
1226
|
-
roots.push(providerUsage);
|
|
1227
|
-
}
|
|
1198
|
+
var PI_USAGE_FIELDS = [
|
|
1199
|
+
["input", "inputTokens"],
|
|
1200
|
+
["output", "outputTokens"],
|
|
1201
|
+
["cacheRead", "cachedInputTokens"],
|
|
1202
|
+
["cacheWrite", "cacheCreationTokens"],
|
|
1203
|
+
["totalTokens", "totalTokens"]
|
|
1204
|
+
];
|
|
1205
|
+
function readPiUsage(source) {
|
|
1206
|
+
const record = asRecord(source);
|
|
1207
|
+
if (!record) {
|
|
1208
|
+
return {};
|
|
1228
1209
|
}
|
|
1229
|
-
const
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
const
|
|
1233
|
-
if (
|
|
1234
|
-
|
|
1210
|
+
const usage = asRecord(record.usage) ?? record;
|
|
1211
|
+
const summary = {};
|
|
1212
|
+
for (const [piKey, ourKey] of PI_USAGE_FIELDS) {
|
|
1213
|
+
const value = toFiniteTokenCount(usage[piKey]);
|
|
1214
|
+
if (value !== void 0) {
|
|
1215
|
+
summary[ourKey] = value;
|
|
1235
1216
|
}
|
|
1236
1217
|
}
|
|
1237
|
-
return
|
|
1218
|
+
return summary;
|
|
1238
1219
|
}
|
|
1239
1220
|
function extractGenAiUsageSummary(...sources) {
|
|
1240
|
-
const
|
|
1241
|
-
|
|
1242
|
-
|
|
1221
|
+
const summary = {};
|
|
1222
|
+
for (const source of sources) {
|
|
1223
|
+
const single = readPiUsage(source);
|
|
1224
|
+
for (const field of Object.keys(single)) {
|
|
1225
|
+
const value = single[field];
|
|
1226
|
+
if (value === void 0) continue;
|
|
1227
|
+
summary[field] = (summary[field] ?? 0) + value;
|
|
1228
|
+
}
|
|
1243
1229
|
}
|
|
1244
|
-
|
|
1245
|
-
(root) => readTokenCount(root, [
|
|
1246
|
-
"input_tokens",
|
|
1247
|
-
"inputTokens",
|
|
1248
|
-
"prompt_tokens",
|
|
1249
|
-
"promptTokens",
|
|
1250
|
-
"inputTokenCount",
|
|
1251
|
-
"promptTokenCount"
|
|
1252
|
-
])
|
|
1253
|
-
).find((value) => value !== void 0) ?? void 0;
|
|
1254
|
-
const outputTokens = roots.map(
|
|
1255
|
-
(root) => readTokenCount(root, [
|
|
1256
|
-
"output_tokens",
|
|
1257
|
-
"outputTokens",
|
|
1258
|
-
"completion_tokens",
|
|
1259
|
-
"completionTokens",
|
|
1260
|
-
"outputTokenCount",
|
|
1261
|
-
"completionTokenCount"
|
|
1262
|
-
])
|
|
1263
|
-
).find((value) => value !== void 0) ?? void 0;
|
|
1264
|
-
const totalTokens = roots.map(
|
|
1265
|
-
(root) => readTokenCount(root, [
|
|
1266
|
-
"total_tokens",
|
|
1267
|
-
"totalTokens",
|
|
1268
|
-
"totalTokenCount"
|
|
1269
|
-
])
|
|
1270
|
-
).find((value) => value !== void 0) ?? void 0;
|
|
1271
|
-
return {
|
|
1272
|
-
...inputTokens !== void 0 ? { inputTokens } : {},
|
|
1273
|
-
...outputTokens !== void 0 ? { outputTokens } : {},
|
|
1274
|
-
...totalTokens !== void 0 ? { totalTokens } : {}
|
|
1275
|
-
};
|
|
1230
|
+
return summary;
|
|
1276
1231
|
}
|
|
1277
1232
|
function extractGenAiUsageAttributes(...sources) {
|
|
1278
1233
|
const { inputTokens, outputTokens } = extractGenAiUsageSummary(...sources);
|
|
@@ -1290,6 +1245,7 @@ var SHORT_CAPABILITY_RE = /^[a-z0-9-]+(\.[a-z0-9-]+)*$/;
|
|
|
1290
1245
|
var SHORT_CONFIG_KEY_RE = /^[a-z0-9]+(\.[a-z0-9-]+)*$/;
|
|
1291
1246
|
var TARGET_FLAG_RE = /^-{1,2}[A-Za-z0-9][A-Za-z0-9-]*$/;
|
|
1292
1247
|
var AUTH_TOKEN_ENV_RE = /^[A-Z][A-Z0-9_]*$/;
|
|
1248
|
+
var ENV_VAR_NAME_RE = /^[A-Z_][A-Z0-9_]*$/;
|
|
1293
1249
|
var API_DOMAIN_RE = /^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/;
|
|
1294
1250
|
var RUNTIME_POSTINSTALL_CMD_RE = /^[A-Za-z0-9._/-]+$/;
|
|
1295
1251
|
var RESERVED_AUTHORIZE_PARAM_KEYS = /* @__PURE__ */ new Set([
|
|
@@ -1486,6 +1442,9 @@ var manifestSourceSchema = z.object({
|
|
|
1486
1442
|
"runtime-postinstall": z.array(z.unknown(), {
|
|
1487
1443
|
error: "must be an array"
|
|
1488
1444
|
}).optional(),
|
|
1445
|
+
"env-vars": z.record(z.string(), z.unknown(), {
|
|
1446
|
+
error: "must be an object"
|
|
1447
|
+
}).optional(),
|
|
1489
1448
|
mcp: z.record(z.string(), z.unknown(), {
|
|
1490
1449
|
error: "must be an object"
|
|
1491
1450
|
}).optional(),
|
|
@@ -1691,8 +1650,67 @@ function normalizeRuntimePostinstall(commands, name) {
|
|
|
1691
1650
|
}
|
|
1692
1651
|
return parsed.length > 0 ? parsed : void 0;
|
|
1693
1652
|
}
|
|
1694
|
-
|
|
1695
|
-
|
|
1653
|
+
var ENV_PLACEHOLDER_RE = /\$\{([A-Z_][A-Z0-9_]*)\}/g;
|
|
1654
|
+
var envVarDeclarationSchema = z.preprocess(
|
|
1655
|
+
(value) => value === null || value === void 0 ? {} : value,
|
|
1656
|
+
z.object({
|
|
1657
|
+
default: z.string().optional()
|
|
1658
|
+
}).passthrough()
|
|
1659
|
+
);
|
|
1660
|
+
function normalizeEnvVars(data, pluginName) {
|
|
1661
|
+
const normalized = {};
|
|
1662
|
+
for (const [rawName, rawDecl] of Object.entries(data)) {
|
|
1663
|
+
const name = rawName.trim();
|
|
1664
|
+
if (!ENV_VAR_NAME_RE.test(name)) {
|
|
1665
|
+
throw new Error(
|
|
1666
|
+
`Plugin ${pluginName} env-vars key "${rawName}" must match [A-Z_][A-Z0-9_]*`
|
|
1667
|
+
);
|
|
1668
|
+
}
|
|
1669
|
+
const parsed = envVarDeclarationSchema.safeParse(rawDecl);
|
|
1670
|
+
if (!parsed.success) {
|
|
1671
|
+
throw new Error(
|
|
1672
|
+
issueMessage(parsed.error, `Plugin ${pluginName} env-vars.${name}`)
|
|
1673
|
+
);
|
|
1674
|
+
}
|
|
1675
|
+
const decl = {};
|
|
1676
|
+
if (parsed.data.default !== void 0) {
|
|
1677
|
+
decl.default = parsed.data.default;
|
|
1678
|
+
}
|
|
1679
|
+
normalized[name] = decl;
|
|
1680
|
+
}
|
|
1681
|
+
return normalized;
|
|
1682
|
+
}
|
|
1683
|
+
function expandEnvPlaceholders(template, envVars, context) {
|
|
1684
|
+
return template.replace(ENV_PLACEHOLDER_RE, (_match, name) => {
|
|
1685
|
+
const varName = name;
|
|
1686
|
+
if (!Object.prototype.hasOwnProperty.call(envVars, varName)) {
|
|
1687
|
+
throw new Error(
|
|
1688
|
+
`${context} references env var ${varName} which is not declared in env-vars`
|
|
1689
|
+
);
|
|
1690
|
+
}
|
|
1691
|
+
const decl = envVars[varName];
|
|
1692
|
+
const fromProcess = process.env[varName];
|
|
1693
|
+
if (fromProcess !== void 0 && fromProcess !== "") {
|
|
1694
|
+
return fromProcess;
|
|
1695
|
+
}
|
|
1696
|
+
if (decl.default !== void 0) {
|
|
1697
|
+
return decl.default;
|
|
1698
|
+
}
|
|
1699
|
+
throw new Error(
|
|
1700
|
+
`${context} env var ${varName} is unset and has no default in env-vars`
|
|
1701
|
+
);
|
|
1702
|
+
});
|
|
1703
|
+
}
|
|
1704
|
+
function normalizeMcp(data, envVars, name) {
|
|
1705
|
+
const prepared = { ...data };
|
|
1706
|
+
if (typeof prepared.url === "string") {
|
|
1707
|
+
prepared.url = expandEnvPlaceholders(
|
|
1708
|
+
prepared.url,
|
|
1709
|
+
envVars,
|
|
1710
|
+
`Plugin ${name} mcp.url`
|
|
1711
|
+
);
|
|
1712
|
+
}
|
|
1713
|
+
const result = mcpSourceSchema.safeParse(prepared);
|
|
1696
1714
|
if (!result.success) {
|
|
1697
1715
|
throw new Error(issueMessage(result.error, `Plugin ${name} mcp`));
|
|
1698
1716
|
}
|
|
@@ -1758,6 +1776,11 @@ function parsePluginManifest(raw, dir) {
|
|
|
1758
1776
|
`Plugin ${parsedYaml.name ?? "unknown"} runtime-postinstall must be an array`
|
|
1759
1777
|
);
|
|
1760
1778
|
}
|
|
1779
|
+
if (path3 === "env-vars") {
|
|
1780
|
+
throw new Error(
|
|
1781
|
+
`Plugin ${parsedYaml.name ?? "unknown"} env-vars must be an object`
|
|
1782
|
+
);
|
|
1783
|
+
}
|
|
1761
1784
|
if (path3 === "mcp") {
|
|
1762
1785
|
throw new Error(
|
|
1763
1786
|
`Plugin ${parsedYaml.name ?? "unknown"} mcp must be an object`
|
|
@@ -1793,12 +1816,14 @@ function parsePluginManifest(raw, dir) {
|
|
|
1793
1816
|
const credentials = data.credentials ? normalizeCredentials(data.credentials, data.name) : void 0;
|
|
1794
1817
|
const runtimeDependencies = data["runtime-dependencies"] ? normalizeRuntimeDependencies(data["runtime-dependencies"], data.name) : void 0;
|
|
1795
1818
|
const runtimePostinstall = data["runtime-postinstall"] ? normalizeRuntimePostinstall(data["runtime-postinstall"], data.name) : void 0;
|
|
1796
|
-
const
|
|
1819
|
+
const envVars = data["env-vars"] ? normalizeEnvVars(data["env-vars"], data.name) : {};
|
|
1820
|
+
const mcp = data.mcp ? normalizeMcp(data.mcp, envVars, data.name) : void 0;
|
|
1797
1821
|
const manifest = {
|
|
1798
1822
|
name: data.name,
|
|
1799
1823
|
description: data.description,
|
|
1800
1824
|
capabilities,
|
|
1801
1825
|
configKeys,
|
|
1826
|
+
...Object.keys(envVars).length > 0 ? { envVars } : {},
|
|
1802
1827
|
...credentials ? { credentials } : {},
|
|
1803
1828
|
...runtimeDependencies ? { runtimeDependencies } : {},
|
|
1804
1829
|
...runtimePostinstall ? { runtimePostinstall } : {},
|
|
@@ -1891,27 +1916,6 @@ function resolveAuthTokenPlaceholder(credentials) {
|
|
|
1891
1916
|
|
|
1892
1917
|
// src/chat/plugins/auth/github-app-broker.ts
|
|
1893
1918
|
var MAX_LEASE_MS = 60 * 60 * 1e3;
|
|
1894
|
-
function parseRepoTarget(value) {
|
|
1895
|
-
const trimmed = value.trim();
|
|
1896
|
-
if (!trimmed) {
|
|
1897
|
-
return void 0;
|
|
1898
|
-
}
|
|
1899
|
-
const [repoRef] = trimmed.split("#");
|
|
1900
|
-
const [owner, repo, extra] = repoRef.split("/");
|
|
1901
|
-
if (!owner || !repo || extra) {
|
|
1902
|
-
return void 0;
|
|
1903
|
-
}
|
|
1904
|
-
return {
|
|
1905
|
-
owner: owner.toLowerCase(),
|
|
1906
|
-
repo: repo.toLowerCase()
|
|
1907
|
-
};
|
|
1908
|
-
}
|
|
1909
|
-
function getRepoTarget(target) {
|
|
1910
|
-
if (!target || target.type !== "repo") {
|
|
1911
|
-
return void 0;
|
|
1912
|
-
}
|
|
1913
|
-
return parseRepoTarget(target.value);
|
|
1914
|
-
}
|
|
1915
1919
|
function base64Url(input) {
|
|
1916
1920
|
return Buffer.from(input).toString("base64").replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
1917
1921
|
}
|
|
@@ -2017,26 +2021,31 @@ var KNOWN_SCOPES = /* @__PURE__ */ new Set([
|
|
|
2017
2021
|
"vulnerability_alerts",
|
|
2018
2022
|
"workflows"
|
|
2019
2023
|
]);
|
|
2020
|
-
function
|
|
2024
|
+
function capabilitiesToPermissions(capabilities, pluginName) {
|
|
2025
|
+
const permissions = {};
|
|
2021
2026
|
const prefix = `${pluginName}.`;
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2027
|
+
for (const capability of capabilities) {
|
|
2028
|
+
if (!capability.startsWith(prefix)) {
|
|
2029
|
+
throw new Error(`Unsupported GitHub capability: ${capability}`);
|
|
2030
|
+
}
|
|
2031
|
+
const suffix = capability.slice(prefix.length);
|
|
2032
|
+
const lastDot = suffix.lastIndexOf(".");
|
|
2033
|
+
if (lastDot === -1) {
|
|
2034
|
+
throw new Error(`Unsupported GitHub capability: ${capability}`);
|
|
2035
|
+
}
|
|
2036
|
+
const scopeRaw = suffix.slice(0, lastDot);
|
|
2037
|
+
const level = suffix.slice(lastDot + 1);
|
|
2038
|
+
if (level !== "read" && level !== "write") {
|
|
2039
|
+
throw new Error(`Unsupported GitHub capability: ${capability}`);
|
|
2040
|
+
}
|
|
2041
|
+
const scope = scopeRaw.replace(/-/g, "_");
|
|
2042
|
+
if (!KNOWN_SCOPES.has(scope)) {
|
|
2043
|
+
throw new Error(`Unsupported GitHub capability: ${capability}`);
|
|
2044
|
+
}
|
|
2045
|
+
const existing = permissions[scope];
|
|
2046
|
+
permissions[scope] = existing === "write" || level === "write" ? "write" : "read";
|
|
2038
2047
|
}
|
|
2039
|
-
return
|
|
2048
|
+
return permissions;
|
|
2040
2049
|
}
|
|
2041
2050
|
function createGitHubAppBroker(manifest, credentials) {
|
|
2042
2051
|
const tokenCache = /* @__PURE__ */ new Map();
|
|
@@ -2056,16 +2065,19 @@ function createGitHubAppBroker(manifest, credentials) {
|
|
|
2056
2065
|
`${provider}.contents.read`,
|
|
2057
2066
|
`${provider}.contents.write`
|
|
2058
2067
|
]);
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2068
|
+
const leaseDomains = manifest.capabilities.some(
|
|
2069
|
+
(capability) => GIT_CAPABILITIES.has(capability)
|
|
2070
|
+
) ? [...apiDomains, GIT_DOMAIN] : apiDomains;
|
|
2062
2071
|
function authorizationFor(domain, token) {
|
|
2063
2072
|
if (domain === GIT_DOMAIN) {
|
|
2064
2073
|
return `Basic ${Buffer.from(`x-access-token:${token}`).toString("base64")}`;
|
|
2065
2074
|
}
|
|
2066
2075
|
return `Bearer ${token}`;
|
|
2067
2076
|
}
|
|
2068
|
-
const
|
|
2077
|
+
const permissions = capabilitiesToPermissions(
|
|
2078
|
+
manifest.capabilities,
|
|
2079
|
+
provider
|
|
2080
|
+
);
|
|
2069
2081
|
function resolveInstallationId() {
|
|
2070
2082
|
const installationIdRaw = process.env[installationIdEnv]?.trim();
|
|
2071
2083
|
if (!installationIdRaw) {
|
|
@@ -2079,37 +2091,16 @@ function createGitHubAppBroker(manifest, credentials) {
|
|
|
2079
2091
|
}
|
|
2080
2092
|
return {
|
|
2081
2093
|
async issue(input) {
|
|
2082
|
-
if (!supportedCapabilities.has(input.capability)) {
|
|
2083
|
-
throw new Error(
|
|
2084
|
-
`Unsupported ${provider} capability: ${input.capability}`
|
|
2085
|
-
);
|
|
2086
|
-
}
|
|
2087
|
-
const permissions = capabilityToPermissions(input.capability, provider);
|
|
2088
2094
|
const installationId = resolveInstallationId();
|
|
2089
|
-
|
|
2090
|
-
if (input.target) {
|
|
2091
|
-
if (input.target.type !== "repo") {
|
|
2092
|
-
throw new Error(
|
|
2093
|
-
`Unsupported github target type: ${input.target.type}`
|
|
2094
|
-
);
|
|
2095
|
-
}
|
|
2096
|
-
repoTarget = getRepoTarget(input.target);
|
|
2097
|
-
if (!repoTarget) {
|
|
2098
|
-
throw new Error("Invalid github repo target: expected owner/repo");
|
|
2099
|
-
}
|
|
2100
|
-
}
|
|
2101
|
-
const targetScope = repoTarget ? `${repoTarget.owner}/${repoTarget.repo}` : "all";
|
|
2102
|
-
const cacheKey = `${installationId}:${input.capability}:${targetScope}`;
|
|
2095
|
+
const cacheKey = String(installationId);
|
|
2103
2096
|
const cached = tokenCache.get(cacheKey);
|
|
2104
2097
|
const now = Date.now();
|
|
2105
2098
|
if (cached && cached.expiresAt - now > 2 * 60 * 1e3) {
|
|
2106
|
-
const domains2 = leaseDomainsFor(input.capability);
|
|
2107
2099
|
return {
|
|
2108
2100
|
id: randomUUID(),
|
|
2109
2101
|
provider,
|
|
2110
|
-
capability: input.capability,
|
|
2111
2102
|
env: { [authTokenEnv]: placeholder },
|
|
2112
|
-
headerTransforms:
|
|
2103
|
+
headerTransforms: leaseDomains.map((domain) => ({
|
|
2113
2104
|
domain,
|
|
2114
2105
|
headers: {
|
|
2115
2106
|
...apiHeaders ?? {},
|
|
@@ -2119,7 +2110,6 @@ function createGitHubAppBroker(manifest, credentials) {
|
|
|
2119
2110
|
expiresAt: new Date(cached.expiresAt).toISOString(),
|
|
2120
2111
|
metadata: {
|
|
2121
2112
|
installationId: String(cached.installationId),
|
|
2122
|
-
targetScope,
|
|
2123
2113
|
reason: input.reason
|
|
2124
2114
|
}
|
|
2125
2115
|
};
|
|
@@ -2127,9 +2117,6 @@ function createGitHubAppBroker(manifest, credentials) {
|
|
|
2127
2117
|
const tokenRequestBody = {
|
|
2128
2118
|
permissions
|
|
2129
2119
|
};
|
|
2130
|
-
if (repoTarget) {
|
|
2131
|
-
tokenRequestBody.repositories = [repoTarget.repo];
|
|
2132
|
-
}
|
|
2133
2120
|
const appId = process.env[appIdEnv];
|
|
2134
2121
|
if (!appId) {
|
|
2135
2122
|
throw new Error(`Missing ${appIdEnv}`);
|
|
@@ -2150,13 +2137,11 @@ function createGitHubAppBroker(manifest, credentials) {
|
|
|
2150
2137
|
token: accessTokenResponse.token,
|
|
2151
2138
|
expiresAt: expiresAtMs
|
|
2152
2139
|
});
|
|
2153
|
-
const domains = leaseDomainsFor(input.capability);
|
|
2154
2140
|
return {
|
|
2155
2141
|
id: randomUUID(),
|
|
2156
2142
|
provider,
|
|
2157
|
-
capability: input.capability,
|
|
2158
2143
|
env: { [authTokenEnv]: placeholder },
|
|
2159
|
-
headerTransforms:
|
|
2144
|
+
headerTransforms: leaseDomains.map((domain) => ({
|
|
2160
2145
|
domain,
|
|
2161
2146
|
headers: {
|
|
2162
2147
|
...apiHeaders ?? {},
|
|
@@ -2166,7 +2151,6 @@ function createGitHubAppBroker(manifest, credentials) {
|
|
|
2166
2151
|
expiresAt: new Date(expiresAtMs).toISOString(),
|
|
2167
2152
|
metadata: {
|
|
2168
2153
|
installationId: String(installationId),
|
|
2169
|
-
targetScope,
|
|
2170
2154
|
reason: input.reason
|
|
2171
2155
|
}
|
|
2172
2156
|
};
|
|
@@ -2322,14 +2306,12 @@ function getLeaseExpiry(expiresAt) {
|
|
|
2322
2306
|
}
|
|
2323
2307
|
function createOAuthBearerBroker(manifest, credentials, deps) {
|
|
2324
2308
|
const provider = manifest.name;
|
|
2325
|
-
const supportedCapabilities = new Set(manifest.capabilities);
|
|
2326
2309
|
const { apiDomains, apiHeaders, authTokenEnv } = credentials;
|
|
2327
2310
|
const authTokenPlaceholder = resolveAuthTokenPlaceholder(credentials);
|
|
2328
|
-
function buildLease(token,
|
|
2311
|
+
function buildLease(token, expiresAtMs, reason) {
|
|
2329
2312
|
return {
|
|
2330
2313
|
id: randomUUID2(),
|
|
2331
2314
|
provider,
|
|
2332
|
-
capability,
|
|
2333
2315
|
env: { [authTokenEnv]: authTokenPlaceholder },
|
|
2334
2316
|
headerTransforms: apiDomains.map((domain) => ({
|
|
2335
2317
|
domain,
|
|
@@ -2341,21 +2323,11 @@ function createOAuthBearerBroker(manifest, credentials, deps) {
|
|
|
2341
2323
|
}
|
|
2342
2324
|
return {
|
|
2343
2325
|
async issue(input) {
|
|
2344
|
-
if (!supportedCapabilities.has(input.capability)) {
|
|
2345
|
-
throw new Error(
|
|
2346
|
-
`Unsupported ${provider} capability: ${input.capability}`
|
|
2347
|
-
);
|
|
2348
|
-
}
|
|
2349
2326
|
const envToken = process.env[authTokenEnv]?.trim();
|
|
2350
2327
|
const oauth = manifest.oauth;
|
|
2351
2328
|
if (!oauth) {
|
|
2352
2329
|
if (envToken) {
|
|
2353
|
-
return buildLease(
|
|
2354
|
-
envToken,
|
|
2355
|
-
input.capability,
|
|
2356
|
-
Date.now() + MAX_LEASE_MS2,
|
|
2357
|
-
input.reason
|
|
2358
|
-
);
|
|
2330
|
+
return buildLease(envToken, Date.now() + MAX_LEASE_MS2, input.reason);
|
|
2359
2331
|
}
|
|
2360
2332
|
throw new CredentialUnavailableError(
|
|
2361
2333
|
provider,
|
|
@@ -2395,7 +2367,6 @@ function createOAuthBearerBroker(manifest, credentials, deps) {
|
|
|
2395
2367
|
);
|
|
2396
2368
|
return buildLease(
|
|
2397
2369
|
refreshed.accessToken,
|
|
2398
|
-
input.capability,
|
|
2399
2370
|
getLeaseExpiry(refreshed.expiresAt),
|
|
2400
2371
|
input.reason
|
|
2401
2372
|
);
|
|
@@ -2406,7 +2377,6 @@ function createOAuthBearerBroker(manifest, credentials, deps) {
|
|
|
2406
2377
|
if (stored.expiresAt > Date.now()) {
|
|
2407
2378
|
return buildLease(
|
|
2408
2379
|
stored.accessToken,
|
|
2409
|
-
input.capability,
|
|
2410
2380
|
getLeaseExpiry(stored.expiresAt),
|
|
2411
2381
|
input.reason
|
|
2412
2382
|
);
|
|
@@ -2420,7 +2390,6 @@ function createOAuthBearerBroker(manifest, credentials, deps) {
|
|
|
2420
2390
|
if (stored.expiresAt === void 0 || stored.expiresAt > Date.now()) {
|
|
2421
2391
|
return buildLease(
|
|
2422
2392
|
stored.accessToken,
|
|
2423
|
-
input.capability,
|
|
2424
2393
|
getLeaseExpiry(stored.expiresAt),
|
|
2425
2394
|
input.reason
|
|
2426
2395
|
);
|
|
@@ -2436,12 +2405,7 @@ function createOAuthBearerBroker(manifest, credentials, deps) {
|
|
|
2436
2405
|
);
|
|
2437
2406
|
}
|
|
2438
2407
|
if (envToken) {
|
|
2439
|
-
return buildLease(
|
|
2440
|
-
envToken,
|
|
2441
|
-
input.capability,
|
|
2442
|
-
getLeaseExpiry(),
|
|
2443
|
-
input.reason
|
|
2444
|
-
);
|
|
2408
|
+
return buildLease(envToken, getLeaseExpiry(), input.reason);
|
|
2445
2409
|
}
|
|
2446
2410
|
throw new CredentialUnavailableError(
|
|
2447
2411
|
provider,
|
package/dist/cli/check.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
parseSkillFile
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-ICIRAL6Y.js";
|
|
4
4
|
import {
|
|
5
5
|
parsePluginManifest
|
|
6
|
-
} from "../chunk-
|
|
6
|
+
} from "../chunk-RZJDO55D.js";
|
|
7
7
|
import "../chunk-Z3YD6NHK.js";
|
|
8
8
|
import "../chunk-XPXD3FCE.js";
|
|
9
9
|
import "../chunk-2KG3PWR4.js";
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
disconnectStateAdapter,
|
|
3
3
|
resolveRuntimeDependencySnapshot
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-A75TWGF2.js";
|
|
5
5
|
import {
|
|
6
6
|
getPluginProviders,
|
|
7
7
|
getPluginRuntimeDependencies,
|
|
8
8
|
getPluginRuntimePostinstall
|
|
9
|
-
} from "../chunk-
|
|
9
|
+
} from "../chunk-RZJDO55D.js";
|
|
10
10
|
import "../chunk-Z3YD6NHK.js";
|
|
11
11
|
import "../chunk-XPXD3FCE.js";
|
|
12
12
|
import "../chunk-2KG3PWR4.js";
|