@sentry/junior 0.41.0 → 0.43.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 +1178 -450
- package/dist/{chunk-SCE5C645.js → chunk-BCG3I2T2.js} +197 -101
- package/dist/{chunk-Y3UO7NR6.js → chunk-YSXHRIWR.js} +47 -10
- package/dist/{chunk-7QYONRLH.js → chunk-ZUUJTQ2H.js} +1 -1
- package/dist/cli/check.js +30 -11
- package/dist/cli/snapshot-warmup.js +2 -2
- package/package.json +3 -2
|
@@ -1347,7 +1347,7 @@ var stringMapSchema = z.record(z.string(), z.unknown()).transform((record, ctx)
|
|
|
1347
1347
|
}
|
|
1348
1348
|
return result;
|
|
1349
1349
|
});
|
|
1350
|
-
var
|
|
1350
|
+
var domainsSchema = z.array(z.unknown()).min(1, {
|
|
1351
1351
|
error: "must be a non-empty array of strings"
|
|
1352
1352
|
}).transform((domains, ctx) => {
|
|
1353
1353
|
return domains.map((rawDomain) => {
|
|
@@ -1370,7 +1370,7 @@ var apiDomainsSchema = z.array(z.unknown()).min(1, {
|
|
|
1370
1370
|
});
|
|
1371
1371
|
});
|
|
1372
1372
|
var baseCredentialsSchema = z.object({
|
|
1373
|
-
|
|
1373
|
+
domains: domainsSchema.optional(),
|
|
1374
1374
|
"api-headers": stringMapSchema.optional(),
|
|
1375
1375
|
"auth-token-env": envVarString,
|
|
1376
1376
|
"auth-token-placeholder": nonEmptyTrimmedString.optional()
|
|
@@ -1438,7 +1438,7 @@ var manifestSourceSchema = z.object({
|
|
|
1438
1438
|
"config-keys": z.array(z.string(), {
|
|
1439
1439
|
error: "must be an array when provided"
|
|
1440
1440
|
}).optional(),
|
|
1441
|
-
|
|
1441
|
+
domains: domainsSchema.optional(),
|
|
1442
1442
|
"api-headers": stringMapSchema.optional(),
|
|
1443
1443
|
"command-env": stringMapSchema.optional(),
|
|
1444
1444
|
credentials: z.record(z.string(), z.unknown(), {
|
|
@@ -1493,9 +1493,13 @@ function normalizeStringMap(value, prefix, options = {}) {
|
|
|
1493
1493
|
}
|
|
1494
1494
|
return value;
|
|
1495
1495
|
}
|
|
1496
|
+
function envReferences(value) {
|
|
1497
|
+
return Array.from(value.matchAll(ENV_PLACEHOLDER_RE), (match) => {
|
|
1498
|
+
return match[1];
|
|
1499
|
+
});
|
|
1500
|
+
}
|
|
1496
1501
|
function assertDeclaredEnvReferences(value, envVars, context) {
|
|
1497
|
-
for (const
|
|
1498
|
-
const name = match[1];
|
|
1502
|
+
for (const name of envReferences(value)) {
|
|
1499
1503
|
if (!Object.prototype.hasOwnProperty.call(envVars, name)) {
|
|
1500
1504
|
throw new Error(
|
|
1501
1505
|
`${context} references env var ${name} which is not declared in env-vars`
|
|
@@ -1518,21 +1522,25 @@ function normalizeRequiredApiHeaders(value, prefix, envVars) {
|
|
|
1518
1522
|
}
|
|
1519
1523
|
return apiHeaders;
|
|
1520
1524
|
}
|
|
1521
|
-
function
|
|
1522
|
-
for (const
|
|
1523
|
-
const name = match[1];
|
|
1525
|
+
function assertCommandEnvReferencesDeclared(value, envVars, context) {
|
|
1526
|
+
for (const name of envReferences(value)) {
|
|
1524
1527
|
if (!Object.prototype.hasOwnProperty.call(envVars, name)) {
|
|
1525
1528
|
throw new Error(
|
|
1526
1529
|
`${context} references env var ${name} which is not declared in env-vars`
|
|
1527
1530
|
);
|
|
1528
1531
|
}
|
|
1529
|
-
if (envVars[name]?.default === void 0) {
|
|
1530
|
-
throw new Error(
|
|
1531
|
-
`${context} references env var ${name}, but command-env env vars must declare defaults`
|
|
1532
|
-
);
|
|
1533
|
-
}
|
|
1534
1532
|
}
|
|
1535
1533
|
}
|
|
1534
|
+
function expandCommandEnvPlaceholders(template, envVars, context) {
|
|
1535
|
+
return template.replace(ENV_PLACEHOLDER_RE, (match, name) => {
|
|
1536
|
+
const varName = name;
|
|
1537
|
+
const declaration = envVars[varName];
|
|
1538
|
+
if (declaration?.default === void 0) {
|
|
1539
|
+
return match;
|
|
1540
|
+
}
|
|
1541
|
+
return expandEnvPlaceholders(match, envVars, context);
|
|
1542
|
+
});
|
|
1543
|
+
}
|
|
1536
1544
|
function normalizeCommandEnv(value, prefix, envVars) {
|
|
1537
1545
|
const env = normalizeStringMap(value, prefix);
|
|
1538
1546
|
if (!env) {
|
|
@@ -1542,15 +1550,47 @@ function normalizeCommandEnv(value, prefix, envVars) {
|
|
|
1542
1550
|
if (!ENV_VAR_NAME_RE.test(key)) {
|
|
1543
1551
|
throw new Error(`${prefix}.${key} must be an uppercase env var name`);
|
|
1544
1552
|
}
|
|
1545
|
-
|
|
1553
|
+
assertCommandEnvReferencesDeclared(envValue, envVars, `${prefix}.${key}`);
|
|
1546
1554
|
}
|
|
1547
1555
|
return Object.fromEntries(
|
|
1548
1556
|
Object.entries(env).map(([key, envValue]) => [
|
|
1549
1557
|
key,
|
|
1550
|
-
|
|
1558
|
+
expandCommandEnvPlaceholders(envValue, envVars, `${prefix}.${key}`)
|
|
1551
1559
|
])
|
|
1552
1560
|
);
|
|
1553
1561
|
}
|
|
1562
|
+
function assertCommandEnvDoesNotExposeHostSecretRefs(commandEnv, apiHeaders, credentials, oauth, pluginName) {
|
|
1563
|
+
if (!commandEnv) {
|
|
1564
|
+
return;
|
|
1565
|
+
}
|
|
1566
|
+
const hostOnlyRefs = /* @__PURE__ */ new Set();
|
|
1567
|
+
for (const value of Object.values(apiHeaders ?? {})) {
|
|
1568
|
+
for (const name of envReferences(value)) {
|
|
1569
|
+
hostOnlyRefs.add(name);
|
|
1570
|
+
}
|
|
1571
|
+
}
|
|
1572
|
+
if (credentials) {
|
|
1573
|
+
hostOnlyRefs.add(credentials.authTokenEnv);
|
|
1574
|
+
if (credentials.type === "github-app") {
|
|
1575
|
+
hostOnlyRefs.add(credentials.appIdEnv);
|
|
1576
|
+
hostOnlyRefs.add(credentials.privateKeyEnv);
|
|
1577
|
+
hostOnlyRefs.add(credentials.installationIdEnv);
|
|
1578
|
+
}
|
|
1579
|
+
}
|
|
1580
|
+
if (oauth) {
|
|
1581
|
+
hostOnlyRefs.add(oauth.clientIdEnv);
|
|
1582
|
+
hostOnlyRefs.add(oauth.clientSecretEnv);
|
|
1583
|
+
}
|
|
1584
|
+
for (const [key, value] of Object.entries(commandEnv)) {
|
|
1585
|
+
for (const name of envReferences(value)) {
|
|
1586
|
+
if (hostOnlyRefs.has(name)) {
|
|
1587
|
+
throw new Error(
|
|
1588
|
+
`Plugin ${pluginName} command-env.${key} references env var ${name}, but credential/API header env vars must stay host-only`
|
|
1589
|
+
);
|
|
1590
|
+
}
|
|
1591
|
+
}
|
|
1592
|
+
}
|
|
1593
|
+
}
|
|
1554
1594
|
function normalizeCredentials(data, name) {
|
|
1555
1595
|
const schema = data.type === "oauth-bearer" ? oauthBearerCredentialsSchema : data.type === "github-app" ? githubAppCredentialsSchema : void 0;
|
|
1556
1596
|
if (!schema) {
|
|
@@ -1562,6 +1602,10 @@ function normalizeCredentials(data, name) {
|
|
|
1562
1602
|
if (!result.success) {
|
|
1563
1603
|
throw new Error(issueMessage(result.error, `Plugin ${name} credentials`));
|
|
1564
1604
|
}
|
|
1605
|
+
if (!result.data.domains) {
|
|
1606
|
+
throw new Error(`Plugin ${name} credentials requires domains`);
|
|
1607
|
+
}
|
|
1608
|
+
const domains = result.data.domains;
|
|
1565
1609
|
if (result.data.type === "oauth-bearer") {
|
|
1566
1610
|
const apiHeaders2 = result.data["api-headers"] ? normalizeStringMap(
|
|
1567
1611
|
result.data["api-headers"],
|
|
@@ -1570,7 +1614,7 @@ function normalizeCredentials(data, name) {
|
|
|
1570
1614
|
) : void 0;
|
|
1571
1615
|
return {
|
|
1572
1616
|
type: "oauth-bearer",
|
|
1573
|
-
|
|
1617
|
+
domains,
|
|
1574
1618
|
...apiHeaders2 ? { apiHeaders: apiHeaders2 } : {},
|
|
1575
1619
|
authTokenEnv: result.data["auth-token-env"],
|
|
1576
1620
|
...result.data["auth-token-placeholder"] ? { authTokenPlaceholder: result.data["auth-token-placeholder"] } : {}
|
|
@@ -1583,7 +1627,7 @@ function normalizeCredentials(data, name) {
|
|
|
1583
1627
|
) : void 0;
|
|
1584
1628
|
return {
|
|
1585
1629
|
type: "github-app",
|
|
1586
|
-
|
|
1630
|
+
domains,
|
|
1587
1631
|
...apiHeaders ? { apiHeaders } : {},
|
|
1588
1632
|
authTokenEnv: result.data["auth-token-env"],
|
|
1589
1633
|
...result.data["auth-token-placeholder"] ? { authTokenPlaceholder: result.data["auth-token-placeholder"] } : {},
|
|
@@ -1722,7 +1766,7 @@ var envVarDeclarationSchema = z.preprocess(
|
|
|
1722
1766
|
(value) => value === null || value === void 0 ? {} : value,
|
|
1723
1767
|
z.object({
|
|
1724
1768
|
default: z.string().optional()
|
|
1725
|
-
}).
|
|
1769
|
+
}).strict()
|
|
1726
1770
|
);
|
|
1727
1771
|
function normalizeEnvVars(data, pluginName) {
|
|
1728
1772
|
const normalized = {};
|
|
@@ -1825,9 +1869,9 @@ function parsePluginManifest(raw, dir) {
|
|
|
1825
1869
|
`Plugin ${parsedYaml.name ?? "unknown"} config-keys must be an array when provided`
|
|
1826
1870
|
);
|
|
1827
1871
|
}
|
|
1828
|
-
if (path3 === "
|
|
1872
|
+
if (path3 === "domains") {
|
|
1829
1873
|
throw new Error(
|
|
1830
|
-
`Plugin ${parsedYaml.name ?? "unknown"}
|
|
1874
|
+
`Plugin ${parsedYaml.name ?? "unknown"} ${path3} must be a non-empty array of domains`
|
|
1831
1875
|
);
|
|
1832
1876
|
}
|
|
1833
1877
|
if (path3 === "api-headers") {
|
|
@@ -1898,11 +1942,14 @@ function parsePluginManifest(raw, dir) {
|
|
|
1898
1942
|
`Plugin ${data.name} api-headers`,
|
|
1899
1943
|
envVars
|
|
1900
1944
|
) : void 0;
|
|
1901
|
-
|
|
1902
|
-
|
|
1945
|
+
const domains = data.domains;
|
|
1946
|
+
if (apiHeaders && !domains) {
|
|
1947
|
+
throw new Error(`Plugin ${data.name} api-headers requires domains`);
|
|
1903
1948
|
}
|
|
1904
|
-
if (
|
|
1905
|
-
throw new Error(
|
|
1949
|
+
if (domains && !apiHeaders && !data.credentials) {
|
|
1950
|
+
throw new Error(
|
|
1951
|
+
`Plugin ${data.name} domains requires credentials or api-headers`
|
|
1952
|
+
);
|
|
1906
1953
|
}
|
|
1907
1954
|
const commandEnv = data["command-env"] ? normalizeCommandEnv(
|
|
1908
1955
|
data["command-env"],
|
|
@@ -1923,7 +1970,7 @@ function parsePluginManifest(raw, dir) {
|
|
|
1923
1970
|
description: data.description,
|
|
1924
1971
|
capabilities,
|
|
1925
1972
|
configKeys,
|
|
1926
|
-
...
|
|
1973
|
+
...domains ? { domains } : {},
|
|
1927
1974
|
...apiHeaders ? { apiHeaders } : {},
|
|
1928
1975
|
...commandEnv ? { commandEnv } : {},
|
|
1929
1976
|
...Object.keys(envVars).length > 0 ? { envVars } : {},
|
|
@@ -1970,6 +2017,13 @@ function parsePluginManifest(raw, dir) {
|
|
|
1970
2017
|
...tokenExtraHeaders ? { tokenExtraHeaders } : {}
|
|
1971
2018
|
};
|
|
1972
2019
|
}
|
|
2020
|
+
assertCommandEnvDoesNotExposeHostSecretRefs(
|
|
2021
|
+
data["command-env"],
|
|
2022
|
+
apiHeaders,
|
|
2023
|
+
credentials,
|
|
2024
|
+
manifest.oauth,
|
|
2025
|
+
data.name
|
|
2026
|
+
);
|
|
1973
2027
|
if (data.target) {
|
|
1974
2028
|
const result = targetSourceSchema.safeParse(data.target);
|
|
1975
2029
|
if (!result.success) {
|
|
@@ -2023,14 +2077,45 @@ function mergeHeaderTransforms(transforms) {
|
|
|
2023
2077
|
}));
|
|
2024
2078
|
}
|
|
2025
2079
|
|
|
2080
|
+
// src/chat/plugins/command-env.ts
|
|
2081
|
+
var ENV_PLACEHOLDER_RE2 = /\$\{([A-Z_][A-Z0-9_]*)\}/g;
|
|
2082
|
+
function resolveValue(manifest, value) {
|
|
2083
|
+
let missing = false;
|
|
2084
|
+
const resolved = value.replace(ENV_PLACEHOLDER_RE2, (match, name) => {
|
|
2085
|
+
const envName = name;
|
|
2086
|
+
const declaration = manifest.envVars?.[envName];
|
|
2087
|
+
if (!declaration || declaration.default !== void 0) {
|
|
2088
|
+
return match;
|
|
2089
|
+
}
|
|
2090
|
+
const hostValue = process.env[envName];
|
|
2091
|
+
if (hostValue === void 0 || hostValue === "") {
|
|
2092
|
+
missing = true;
|
|
2093
|
+
return "";
|
|
2094
|
+
}
|
|
2095
|
+
return hostValue;
|
|
2096
|
+
});
|
|
2097
|
+
return missing ? void 0 : resolved;
|
|
2098
|
+
}
|
|
2099
|
+
function resolvePluginCommandEnv(manifest) {
|
|
2100
|
+
const env = {};
|
|
2101
|
+
for (const [key, value] of Object.entries(manifest.commandEnv ?? {})) {
|
|
2102
|
+
const resolved = resolveValue(manifest, value);
|
|
2103
|
+
if (resolved === void 0) {
|
|
2104
|
+
continue;
|
|
2105
|
+
}
|
|
2106
|
+
env[key] = resolved;
|
|
2107
|
+
}
|
|
2108
|
+
return env;
|
|
2109
|
+
}
|
|
2110
|
+
|
|
2026
2111
|
// src/chat/plugins/auth/api-headers-broker.ts
|
|
2027
2112
|
import { randomUUID } from "crypto";
|
|
2028
2113
|
var MAX_LEASE_MS = 60 * 60 * 1e3;
|
|
2029
|
-
var
|
|
2114
|
+
var ENV_PLACEHOLDER_RE3 = /\$\{([A-Z_][A-Z0-9_]*)\}/g;
|
|
2030
2115
|
function resolveHeaders(provider, headers) {
|
|
2031
2116
|
return Object.fromEntries(
|
|
2032
2117
|
Object.entries(headers).map(([key, value]) => {
|
|
2033
|
-
const resolved = value.replace(
|
|
2118
|
+
const resolved = value.replace(ENV_PLACEHOLDER_RE3, (_match, name) => {
|
|
2034
2119
|
const envName = name;
|
|
2035
2120
|
const envValue = process.env[envName]?.trim();
|
|
2036
2121
|
if (!envValue) {
|
|
@@ -2045,12 +2130,12 @@ function resolveHeaders(provider, headers) {
|
|
|
2045
2130
|
);
|
|
2046
2131
|
}
|
|
2047
2132
|
function resolveApiHeaderTransforms(manifest) {
|
|
2048
|
-
const {
|
|
2049
|
-
if (!
|
|
2133
|
+
const { domains, apiHeaders } = manifest;
|
|
2134
|
+
if (!domains || !apiHeaders) {
|
|
2050
2135
|
return [];
|
|
2051
2136
|
}
|
|
2052
2137
|
const resolvedHeaders = resolveHeaders(manifest.name, apiHeaders);
|
|
2053
|
-
return
|
|
2138
|
+
return domains.map((domain) => ({
|
|
2054
2139
|
domain,
|
|
2055
2140
|
headers: resolvedHeaders
|
|
2056
2141
|
}));
|
|
@@ -2066,7 +2151,7 @@ function createApiHeadersBroker(manifest) {
|
|
|
2066
2151
|
return {
|
|
2067
2152
|
id: randomUUID(),
|
|
2068
2153
|
provider,
|
|
2069
|
-
env:
|
|
2154
|
+
env: resolvePluginCommandEnv(manifest),
|
|
2070
2155
|
headerTransforms,
|
|
2071
2156
|
expiresAt: new Date(Date.now() + MAX_LEASE_MS).toISOString(),
|
|
2072
2157
|
metadata: {
|
|
@@ -2145,6 +2230,13 @@ function createAppJwt(appId, privateKeyEnv) {
|
|
|
2145
2230
|
const signature = signer.sign(getPrivateKey(privateKeyEnv)).toString("base64").replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
2146
2231
|
return `${signingInput}.${signature}`;
|
|
2147
2232
|
}
|
|
2233
|
+
function resolveAppId(appIdEnv) {
|
|
2234
|
+
const appId = process.env[appIdEnv]?.trim();
|
|
2235
|
+
if (!appId) {
|
|
2236
|
+
throw new Error(`Missing ${appIdEnv}`);
|
|
2237
|
+
}
|
|
2238
|
+
return appId;
|
|
2239
|
+
}
|
|
2148
2240
|
async function githubRequest(apiBase, path3, params) {
|
|
2149
2241
|
const response = await fetch(`${apiBase}${path3}`, {
|
|
2150
2242
|
method: params.method ?? "GET",
|
|
@@ -2171,6 +2263,16 @@ async function githubRequest(apiBase, path3, params) {
|
|
|
2171
2263
|
}
|
|
2172
2264
|
return parsed;
|
|
2173
2265
|
}
|
|
2266
|
+
function resolveGitHubApiDomain(credentials) {
|
|
2267
|
+
const apiDomain = credentials.domains.find((domain) => {
|
|
2268
|
+
const normalizedDomain = domain.toLowerCase();
|
|
2269
|
+
return normalizedDomain === "api.github.com" || normalizedDomain.startsWith("api.");
|
|
2270
|
+
});
|
|
2271
|
+
if (!apiDomain) {
|
|
2272
|
+
throw new Error("GitHub App provider requires an API domain");
|
|
2273
|
+
}
|
|
2274
|
+
return apiDomain;
|
|
2275
|
+
}
|
|
2174
2276
|
var KNOWN_SCOPES = /* @__PURE__ */ new Set([
|
|
2175
2277
|
"actions",
|
|
2176
2278
|
"administration",
|
|
@@ -2220,37 +2322,60 @@ function capabilitiesToPermissions(capabilities, pluginName) {
|
|
|
2220
2322
|
return permissions;
|
|
2221
2323
|
}
|
|
2222
2324
|
function createGitHubAppBroker(manifest, credentials) {
|
|
2223
|
-
const tokenCache = /* @__PURE__ */ new Map();
|
|
2224
2325
|
const provider = manifest.name;
|
|
2225
2326
|
const {
|
|
2226
|
-
|
|
2327
|
+
domains,
|
|
2227
2328
|
apiHeaders,
|
|
2228
2329
|
authTokenEnv,
|
|
2229
2330
|
appIdEnv,
|
|
2230
2331
|
privateKeyEnv,
|
|
2231
2332
|
installationIdEnv
|
|
2232
2333
|
} = credentials;
|
|
2233
|
-
const
|
|
2334
|
+
const apiDomain = resolveGitHubApiDomain(credentials);
|
|
2335
|
+
const apiBase = `https://${apiDomain}`;
|
|
2234
2336
|
const placeholder = resolveAuthTokenPlaceholder(credentials);
|
|
2235
2337
|
const pluginHeaderTransforms = () => resolveApiHeaderTransforms(manifest);
|
|
2236
|
-
const
|
|
2237
|
-
const GIT_CAPABILITIES = /* @__PURE__ */ new Set([
|
|
2238
|
-
`${provider}.contents.read`,
|
|
2239
|
-
`${provider}.contents.write`
|
|
2240
|
-
]);
|
|
2241
|
-
const leaseDomains = manifest.capabilities.some(
|
|
2242
|
-
(capability) => GIT_CAPABILITIES.has(capability)
|
|
2243
|
-
) ? [...apiDomains, GIT_DOMAIN] : apiDomains;
|
|
2338
|
+
const leaseDomains = [...new Set(domains)];
|
|
2244
2339
|
function authorizationFor(domain, token) {
|
|
2245
|
-
if (domain
|
|
2340
|
+
if (isGitSmartHttpDomain(domain)) {
|
|
2246
2341
|
return `Basic ${Buffer.from(`x-access-token:${token}`).toString("base64")}`;
|
|
2247
2342
|
}
|
|
2248
2343
|
return `Bearer ${token}`;
|
|
2249
2344
|
}
|
|
2345
|
+
function isGitSmartHttpDomain(domain) {
|
|
2346
|
+
const normalizedDomain = domain.toLowerCase();
|
|
2347
|
+
const normalizedApiDomain = apiDomain.toLowerCase();
|
|
2348
|
+
return normalizedDomain === "github.com" || normalizedApiDomain.startsWith("api.") && normalizedDomain === normalizedApiDomain.slice("api.".length);
|
|
2349
|
+
}
|
|
2250
2350
|
const permissions = capabilitiesToPermissions(
|
|
2251
2351
|
manifest.capabilities,
|
|
2252
2352
|
provider
|
|
2253
2353
|
);
|
|
2354
|
+
function createLease(params) {
|
|
2355
|
+
return {
|
|
2356
|
+
id: randomUUID2(),
|
|
2357
|
+
provider,
|
|
2358
|
+
env: {
|
|
2359
|
+
...resolvePluginCommandEnv(manifest),
|
|
2360
|
+
[authTokenEnv]: placeholder
|
|
2361
|
+
},
|
|
2362
|
+
headerTransforms: mergeHeaderTransforms([
|
|
2363
|
+
...pluginHeaderTransforms(),
|
|
2364
|
+
...leaseDomains.map((domain) => ({
|
|
2365
|
+
domain,
|
|
2366
|
+
headers: {
|
|
2367
|
+
...apiHeaders ?? {},
|
|
2368
|
+
Authorization: authorizationFor(domain, params.token)
|
|
2369
|
+
}
|
|
2370
|
+
}))
|
|
2371
|
+
]),
|
|
2372
|
+
expiresAt: new Date(params.expiresAtMs).toISOString(),
|
|
2373
|
+
metadata: {
|
|
2374
|
+
installationId: String(params.installationId),
|
|
2375
|
+
reason: params.reason
|
|
2376
|
+
}
|
|
2377
|
+
};
|
|
2378
|
+
}
|
|
2254
2379
|
function resolveInstallationId() {
|
|
2255
2380
|
const installationIdRaw = process.env[installationIdEnv]?.trim();
|
|
2256
2381
|
if (!installationIdRaw) {
|
|
@@ -2265,38 +2390,10 @@ function createGitHubAppBroker(manifest, credentials) {
|
|
|
2265
2390
|
return {
|
|
2266
2391
|
async issue(input) {
|
|
2267
2392
|
const installationId = resolveInstallationId();
|
|
2268
|
-
const cacheKey = String(installationId);
|
|
2269
|
-
const cached = tokenCache.get(cacheKey);
|
|
2270
|
-
const now = Date.now();
|
|
2271
|
-
if (cached && cached.expiresAt - now > 2 * 60 * 1e3) {
|
|
2272
|
-
return {
|
|
2273
|
-
id: randomUUID2(),
|
|
2274
|
-
provider,
|
|
2275
|
-
env: { ...manifest.commandEnv ?? {}, [authTokenEnv]: placeholder },
|
|
2276
|
-
headerTransforms: mergeHeaderTransforms([
|
|
2277
|
-
...pluginHeaderTransforms(),
|
|
2278
|
-
...leaseDomains.map((domain) => ({
|
|
2279
|
-
domain,
|
|
2280
|
-
headers: {
|
|
2281
|
-
...apiHeaders ?? {},
|
|
2282
|
-
Authorization: authorizationFor(domain, cached.token)
|
|
2283
|
-
}
|
|
2284
|
-
}))
|
|
2285
|
-
]),
|
|
2286
|
-
expiresAt: new Date(cached.expiresAt).toISOString(),
|
|
2287
|
-
metadata: {
|
|
2288
|
-
installationId: String(cached.installationId),
|
|
2289
|
-
reason: input.reason
|
|
2290
|
-
}
|
|
2291
|
-
};
|
|
2292
|
-
}
|
|
2293
2393
|
const tokenRequestBody = {
|
|
2294
2394
|
permissions
|
|
2295
2395
|
};
|
|
2296
|
-
const appId =
|
|
2297
|
-
if (!appId) {
|
|
2298
|
-
throw new Error(`Missing ${appIdEnv}`);
|
|
2299
|
-
}
|
|
2396
|
+
const appId = resolveAppId(appIdEnv);
|
|
2300
2397
|
const appJwt = createAppJwt(appId, privateKeyEnv);
|
|
2301
2398
|
const accessTokenResponse = await githubRequest(apiBase, `/app/installations/${installationId}/access_tokens`, {
|
|
2302
2399
|
method: "POST",
|
|
@@ -2308,34 +2405,12 @@ function createGitHubAppBroker(manifest, credentials) {
|
|
|
2308
2405
|
providerExpiresAtMs,
|
|
2309
2406
|
Date.now() + MAX_LEASE_MS2
|
|
2310
2407
|
);
|
|
2311
|
-
|
|
2408
|
+
return createLease({
|
|
2312
2409
|
installationId,
|
|
2313
2410
|
token: accessTokenResponse.token,
|
|
2314
|
-
|
|
2411
|
+
expiresAtMs,
|
|
2412
|
+
reason: input.reason
|
|
2315
2413
|
});
|
|
2316
|
-
return {
|
|
2317
|
-
id: randomUUID2(),
|
|
2318
|
-
provider,
|
|
2319
|
-
env: { ...manifest.commandEnv ?? {}, [authTokenEnv]: placeholder },
|
|
2320
|
-
headerTransforms: mergeHeaderTransforms([
|
|
2321
|
-
...pluginHeaderTransforms(),
|
|
2322
|
-
...leaseDomains.map((domain) => ({
|
|
2323
|
-
domain,
|
|
2324
|
-
headers: {
|
|
2325
|
-
...apiHeaders ?? {},
|
|
2326
|
-
Authorization: authorizationFor(
|
|
2327
|
-
domain,
|
|
2328
|
-
accessTokenResponse.token
|
|
2329
|
-
)
|
|
2330
|
-
}
|
|
2331
|
-
}))
|
|
2332
|
-
]),
|
|
2333
|
-
expiresAt: new Date(expiresAtMs).toISOString(),
|
|
2334
|
-
metadata: {
|
|
2335
|
-
installationId: String(installationId),
|
|
2336
|
-
reason: input.reason
|
|
2337
|
-
}
|
|
2338
|
-
};
|
|
2339
2414
|
}
|
|
2340
2415
|
};
|
|
2341
2416
|
}
|
|
@@ -2488,7 +2563,7 @@ function getLeaseExpiry(expiresAt) {
|
|
|
2488
2563
|
}
|
|
2489
2564
|
function createOAuthBearerBroker(manifest, credentials, deps) {
|
|
2490
2565
|
const provider = manifest.name;
|
|
2491
|
-
const {
|
|
2566
|
+
const { domains, apiHeaders, authTokenEnv } = credentials;
|
|
2492
2567
|
const authTokenPlaceholder = resolveAuthTokenPlaceholder(credentials);
|
|
2493
2568
|
const pluginHeaderTransforms = () => resolveApiHeaderTransforms(manifest);
|
|
2494
2569
|
function buildLease(token, expiresAtMs, reason) {
|
|
@@ -2496,12 +2571,12 @@ function createOAuthBearerBroker(manifest, credentials, deps) {
|
|
|
2496
2571
|
id: randomUUID3(),
|
|
2497
2572
|
provider,
|
|
2498
2573
|
env: {
|
|
2499
|
-
...manifest
|
|
2574
|
+
...resolvePluginCommandEnv(manifest),
|
|
2500
2575
|
[authTokenEnv]: authTokenPlaceholder
|
|
2501
2576
|
},
|
|
2502
2577
|
headerTransforms: mergeHeaderTransforms([
|
|
2503
2578
|
...pluginHeaderTransforms(),
|
|
2504
|
-
...
|
|
2579
|
+
...domains.map((domain) => ({
|
|
2505
2580
|
domain,
|
|
2506
2581
|
headers: { ...apiHeaders ?? {}, Authorization: `Bearer ${token}` }
|
|
2507
2582
|
}))
|
|
@@ -2616,15 +2691,24 @@ function createLoadedPluginState(signature) {
|
|
|
2616
2691
|
signature,
|
|
2617
2692
|
pluginDefinitions: [],
|
|
2618
2693
|
capabilityToPlugin: /* @__PURE__ */ new Map(),
|
|
2694
|
+
domainToPlugin: /* @__PURE__ */ new Map(),
|
|
2619
2695
|
pluginConfigKeys: /* @__PURE__ */ new Set(),
|
|
2620
2696
|
pluginsByName: /* @__PURE__ */ new Map(),
|
|
2621
2697
|
packageSkillRoots: /* @__PURE__ */ new Set()
|
|
2622
2698
|
};
|
|
2623
2699
|
}
|
|
2700
|
+
function providerDomains(manifest) {
|
|
2701
|
+
return [
|
|
2702
|
+
.../* @__PURE__ */ new Set([
|
|
2703
|
+
...manifest.credentials?.domains ?? [],
|
|
2704
|
+
...manifest.domains ?? []
|
|
2705
|
+
])
|
|
2706
|
+
].sort((left, right) => left.localeCompare(right));
|
|
2707
|
+
}
|
|
2624
2708
|
function registerPluginManifest(state, raw, pluginDir) {
|
|
2625
2709
|
const manifest = parsePluginManifest(raw, pluginDir);
|
|
2626
2710
|
if (state.pluginsByName.has(manifest.name)) {
|
|
2627
|
-
|
|
2711
|
+
throw new Error(`Duplicate plugin name "${manifest.name}"`);
|
|
2628
2712
|
}
|
|
2629
2713
|
for (const cap of manifest.capabilities) {
|
|
2630
2714
|
if (state.capabilityToPlugin.has(cap)) {
|
|
@@ -2633,6 +2717,14 @@ function registerPluginManifest(state, raw, pluginDir) {
|
|
|
2633
2717
|
);
|
|
2634
2718
|
}
|
|
2635
2719
|
}
|
|
2720
|
+
for (const domain of providerDomains(manifest)) {
|
|
2721
|
+
const owner = state.domainToPlugin.get(domain);
|
|
2722
|
+
if (owner) {
|
|
2723
|
+
throw new Error(
|
|
2724
|
+
`Duplicate provider domain "${domain}" in plugin "${manifest.name}" already declared by plugin "${owner}"`
|
|
2725
|
+
);
|
|
2726
|
+
}
|
|
2727
|
+
}
|
|
2636
2728
|
const definition = {
|
|
2637
2729
|
manifest,
|
|
2638
2730
|
dir: pluginDir,
|
|
@@ -2646,6 +2738,9 @@ function registerPluginManifest(state, raw, pluginDir) {
|
|
|
2646
2738
|
for (const key of manifest.configKeys) {
|
|
2647
2739
|
state.pluginConfigKeys.add(key);
|
|
2648
2740
|
}
|
|
2741
|
+
for (const domain of providerDomains(manifest)) {
|
|
2742
|
+
state.domainToPlugin.set(domain, manifest.name);
|
|
2743
|
+
}
|
|
2649
2744
|
}
|
|
2650
2745
|
function normalizePluginRoots(roots) {
|
|
2651
2746
|
const resolved = [];
|
|
@@ -2967,6 +3062,7 @@ export {
|
|
|
2967
3062
|
extractGenAiUsageSummary,
|
|
2968
3063
|
extractGenAiUsageAttributes,
|
|
2969
3064
|
mergeHeaderTransforms,
|
|
3065
|
+
resolvePluginCommandEnv,
|
|
2970
3066
|
resolveAuthTokenPlaceholder,
|
|
2971
3067
|
parsePluginManifest,
|
|
2972
3068
|
CredentialUnavailableError,
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
serializeGenAiAttribute,
|
|
8
8
|
setSpanAttributes,
|
|
9
9
|
withSpan
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-BCG3I2T2.js";
|
|
11
11
|
|
|
12
12
|
// src/chat/state/adapter.ts
|
|
13
13
|
import { createMemoryState } from "@chat-adapter/state-memory";
|
|
@@ -539,12 +539,13 @@ function buildNonInteractiveCommand(input) {
|
|
|
539
539
|
]
|
|
540
540
|
};
|
|
541
541
|
}
|
|
542
|
-
async function runNonInteractiveCommand(
|
|
543
|
-
|
|
542
|
+
async function runNonInteractiveCommand(sandbox, input) {
|
|
543
|
+
const command = {
|
|
544
544
|
...buildNonInteractiveCommand(input),
|
|
545
545
|
...input.cwd ? { cwd: input.cwd } : {},
|
|
546
546
|
...input.sudo !== void 0 ? { sudo: input.sudo } : {}
|
|
547
|
-
}
|
|
547
|
+
};
|
|
548
|
+
return await sandbox.runCommand(command);
|
|
548
549
|
}
|
|
549
550
|
|
|
550
551
|
// src/chat/sandbox/credentials.ts
|
|
@@ -558,6 +559,39 @@ function getVercelSandboxCredentials() {
|
|
|
558
559
|
return void 0;
|
|
559
560
|
}
|
|
560
561
|
|
|
562
|
+
// src/chat/sandbox/workspace.ts
|
|
563
|
+
function createSandboxInstance(sandbox) {
|
|
564
|
+
return {
|
|
565
|
+
sandboxId: sandbox.name,
|
|
566
|
+
fs: sandbox.fs,
|
|
567
|
+
extendTimeout(duration) {
|
|
568
|
+
return sandbox.extendTimeout(duration);
|
|
569
|
+
},
|
|
570
|
+
mkDir(path) {
|
|
571
|
+
return sandbox.mkDir(path);
|
|
572
|
+
},
|
|
573
|
+
readFileToBuffer(input) {
|
|
574
|
+
return sandbox.readFileToBuffer(input);
|
|
575
|
+
},
|
|
576
|
+
runCommand(input) {
|
|
577
|
+
return sandbox.runCommand(input);
|
|
578
|
+
},
|
|
579
|
+
async snapshot() {
|
|
580
|
+
const snapshot = await sandbox.snapshot();
|
|
581
|
+
return { snapshotId: snapshot.snapshotId };
|
|
582
|
+
},
|
|
583
|
+
stop() {
|
|
584
|
+
return sandbox.stop();
|
|
585
|
+
},
|
|
586
|
+
update(params) {
|
|
587
|
+
return sandbox.update(params);
|
|
588
|
+
},
|
|
589
|
+
writeFiles(files) {
|
|
590
|
+
return sandbox.writeFiles(files);
|
|
591
|
+
}
|
|
592
|
+
};
|
|
593
|
+
}
|
|
594
|
+
|
|
561
595
|
// src/chat/sandbox/paths.ts
|
|
562
596
|
function normalizeWorkspaceRoot(input) {
|
|
563
597
|
const candidate = (input ?? "").trim();
|
|
@@ -906,11 +940,13 @@ async function createDependencySnapshot(profile, runtime, timeoutMs) {
|
|
|
906
940
|
},
|
|
907
941
|
async () => {
|
|
908
942
|
const sandboxCredentials = getVercelSandboxCredentials();
|
|
909
|
-
const sandbox =
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
943
|
+
const sandbox = createSandboxInstance(
|
|
944
|
+
await Sandbox.create({
|
|
945
|
+
timeout: timeoutMs,
|
|
946
|
+
runtime,
|
|
947
|
+
...sandboxCredentials ?? {}
|
|
948
|
+
})
|
|
949
|
+
);
|
|
914
950
|
try {
|
|
915
951
|
await installRuntimeDependencies(sandbox, profile.dependencies);
|
|
916
952
|
await runRuntimePostinstall(sandbox, profile.postinstall);
|
|
@@ -927,7 +963,7 @@ async function createDependencySnapshot(profile, runtime, timeoutMs) {
|
|
|
927
963
|
);
|
|
928
964
|
} finally {
|
|
929
965
|
try {
|
|
930
|
-
await sandbox.stop(
|
|
966
|
+
await sandbox.stop();
|
|
931
967
|
} catch {
|
|
932
968
|
}
|
|
933
969
|
}
|
|
@@ -1144,6 +1180,7 @@ export {
|
|
|
1144
1180
|
buildNonInteractiveShellScript,
|
|
1145
1181
|
runNonInteractiveCommand,
|
|
1146
1182
|
getVercelSandboxCredentials,
|
|
1183
|
+
createSandboxInstance,
|
|
1147
1184
|
getRuntimeDependencyProfileHash,
|
|
1148
1185
|
resolveRuntimeDependencySnapshot,
|
|
1149
1186
|
isSnapshotMissingError
|