@sentry/junior 0.63.0 → 0.65.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/README.md +5 -1
- package/dist/api-reference.d.ts +2 -0
- package/dist/app.d.ts +5 -10
- package/dist/app.js +107 -54
- package/dist/build/virtual-config.d.ts +18 -2
- package/dist/chat/logging.d.ts +12 -2
- package/dist/chat/plugins/agent-hooks.d.ts +4 -4
- package/dist/chat/plugins/command-env.d.ts +1 -1
- package/dist/chat/plugins/inline-manifest-source.d.ts +5 -0
- package/dist/chat/plugins/manifest.d.ts +5 -3
- package/dist/chat/plugins/package-discovery.d.ts +5 -0
- package/dist/chat/plugins/registry.d.ts +2 -2
- package/dist/chat/plugins/types.d.ts +9 -3
- package/dist/chat/state/turn-session.d.ts +1 -1
- package/dist/chunk-5VDO6LSG.js +104 -0
- package/dist/{chunk-ITZ2F7UE.js → chunk-7KZXQNA6.js} +10 -22
- package/dist/{chunk-H652GMDH.js → chunk-EDHJIYHS.js} +323 -90
- package/dist/{chunk-LRVKJAR2.js → chunk-K3JNVV4Q.js} +2 -2
- package/dist/{chunk-5LUISFEY.js → chunk-KVZL5NZS.js} +6 -1
- package/dist/{chunk-PEF6UXTY.js → chunk-OMQ5X5QH.js} +1 -1
- package/dist/{chunk-ITOW4DED.js → chunk-PYU2YB35.js} +2 -2
- package/dist/cli/check.js +9 -4
- package/dist/cli/snapshot-warmup.js +4 -4
- package/dist/nitro.d.ts +10 -3
- package/dist/nitro.js +161 -6
- package/dist/plugins.d.ts +22 -0
- package/dist/reporting.d.ts +1 -1
- package/dist/reporting.js +20 -11
- package/package.json +3 -3
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
discoverInstalledPluginPackageContent,
|
|
6
6
|
normalizePluginPackageNames,
|
|
7
7
|
pluginRoots
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-KVZL5NZS.js";
|
|
9
9
|
|
|
10
10
|
// src/chat/coerce.ts
|
|
11
11
|
function toOptionalString(value) {
|
|
@@ -119,6 +119,16 @@ var CONSOLE_PREVIEW_KEYS = /* @__PURE__ */ new Set([
|
|
|
119
119
|
"gen_ai.tool.call.arguments",
|
|
120
120
|
"gen_ai.tool.call.result"
|
|
121
121
|
]);
|
|
122
|
+
var SENTRY_TAG_ATTRIBUTE_KEYS = /* @__PURE__ */ new Set([
|
|
123
|
+
"app.platform",
|
|
124
|
+
"messaging.system",
|
|
125
|
+
"app.actor.type",
|
|
126
|
+
"gen_ai.agent.name",
|
|
127
|
+
"gen_ai.request.model",
|
|
128
|
+
"app.skill.name",
|
|
129
|
+
"http.request.method",
|
|
130
|
+
"url.path"
|
|
131
|
+
]);
|
|
122
132
|
function getSentryEnvironment() {
|
|
123
133
|
return (process.env.SENTRY_ENVIRONMENT ?? process.env.VERCEL_ENV ?? process.env.NODE_ENV ?? "").trim().toLowerCase();
|
|
124
134
|
}
|
|
@@ -857,7 +867,7 @@ var log = {
|
|
|
857
867
|
error(eventName, attrs = {}, body) {
|
|
858
868
|
emit("error", eventName, attrs, body);
|
|
859
869
|
},
|
|
860
|
-
exception(eventName, error, attrs = {}, body) {
|
|
870
|
+
exception(eventName, error, attrs = {}, body, context) {
|
|
861
871
|
const normalizedError = error instanceof Error ? error : new Error(String(error));
|
|
862
872
|
emit(
|
|
863
873
|
"error",
|
|
@@ -876,6 +886,9 @@ var log = {
|
|
|
876
886
|
const sentryCaptureException = sentry_exports.captureException;
|
|
877
887
|
if (typeof sentryWithScope === "function" && typeof sentryCaptureException === "function") {
|
|
878
888
|
sentryWithScope((scope) => {
|
|
889
|
+
if (context) {
|
|
890
|
+
setSentryScopeContext(scope, context);
|
|
891
|
+
}
|
|
879
892
|
for (const [key, value] of Object.entries(
|
|
880
893
|
mergeAttributes(contextStorage.getStore(), attrs)
|
|
881
894
|
)) {
|
|
@@ -886,6 +899,9 @@ var log = {
|
|
|
886
899
|
return eventId;
|
|
887
900
|
}
|
|
888
901
|
if (typeof sentryCaptureException === "function") {
|
|
902
|
+
if (context) {
|
|
903
|
+
setSentryUser(sentryUserIdentityFromContext(context));
|
|
904
|
+
}
|
|
889
905
|
eventId = sentryCaptureException(normalizedError);
|
|
890
906
|
}
|
|
891
907
|
return eventId;
|
|
@@ -1007,16 +1023,51 @@ function toSpanAttributes(context) {
|
|
|
1007
1023
|
function setSentryTagsFromContext(context) {
|
|
1008
1024
|
const attrs = contextToAttributes(context);
|
|
1009
1025
|
for (const [key, value] of Object.entries(attrs)) {
|
|
1026
|
+
if (!SENTRY_TAG_ATTRIBUTE_KEYS.has(key)) {
|
|
1027
|
+
continue;
|
|
1028
|
+
}
|
|
1010
1029
|
if (typeof value === "string" && value.length > 0) {
|
|
1011
1030
|
sentry_exports.setTag(key, value);
|
|
1012
1031
|
}
|
|
1013
1032
|
}
|
|
1033
|
+
}
|
|
1034
|
+
function sentryUserIdentityFromContext(context) {
|
|
1014
1035
|
if (context.slackUserId) {
|
|
1015
|
-
|
|
1036
|
+
return {
|
|
1016
1037
|
id: context.slackUserId,
|
|
1017
|
-
username: context.slackUserName
|
|
1018
|
-
|
|
1038
|
+
...context.slackUserName ? { username: context.slackUserName } : {},
|
|
1039
|
+
...context.slackUserEmail ? { email: context.slackUserEmail } : {}
|
|
1040
|
+
};
|
|
1041
|
+
}
|
|
1042
|
+
return void 0;
|
|
1043
|
+
}
|
|
1044
|
+
function sentryUserFromIdentity(identity) {
|
|
1045
|
+
return {
|
|
1046
|
+
id: identity.id,
|
|
1047
|
+
ip_address: null,
|
|
1048
|
+
...identity.username ? { username: identity.username } : {},
|
|
1049
|
+
...identity.email ? { email: identity.email } : {}
|
|
1050
|
+
};
|
|
1051
|
+
}
|
|
1052
|
+
function setSentryUser(identity) {
|
|
1053
|
+
if (!identity) return;
|
|
1054
|
+
sentry_exports.setUser(sentryUserFromIdentity(identity));
|
|
1055
|
+
}
|
|
1056
|
+
function setSentryScopeContext(scope, context) {
|
|
1057
|
+
const attrs = contextToAttributes(context);
|
|
1058
|
+
for (const [key, value] of Object.entries(attrs)) {
|
|
1059
|
+
if (!SENTRY_TAG_ATTRIBUTE_KEYS.has(key)) {
|
|
1060
|
+
continue;
|
|
1061
|
+
}
|
|
1062
|
+
if (typeof value === "string" && value.length > 0) {
|
|
1063
|
+
scope.setTag(key, value);
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
const identity = sentryUserIdentityFromContext(context);
|
|
1067
|
+
if (identity) {
|
|
1068
|
+
scope.setUser(sentryUserFromIdentity(identity));
|
|
1019
1069
|
}
|
|
1070
|
+
scope.setContext("app", attrs);
|
|
1020
1071
|
}
|
|
1021
1072
|
function toSpanAttributeValue(value) {
|
|
1022
1073
|
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
@@ -1058,12 +1109,14 @@ function logException(error, eventName, context = {}, attributes = {}, body) {
|
|
|
1058
1109
|
eventName,
|
|
1059
1110
|
normalizedError,
|
|
1060
1111
|
{ ...toSpanAttributes(context), ...attributes },
|
|
1061
|
-
body
|
|
1112
|
+
body,
|
|
1113
|
+
context
|
|
1062
1114
|
);
|
|
1063
1115
|
}
|
|
1064
1116
|
function setTags(context = {}) {
|
|
1065
1117
|
setLogContext(context);
|
|
1066
1118
|
setSentryTagsFromContext(context);
|
|
1119
|
+
setSentryUser(sentryUserIdentityFromContext(context));
|
|
1067
1120
|
}
|
|
1068
1121
|
function createRequestContext(request, context = {}) {
|
|
1069
1122
|
return createLogContextFromRequest(request, context);
|
|
@@ -1151,7 +1204,7 @@ function sanitizeGenAiValue(value, seen, depth, keyName) {
|
|
|
1151
1204
|
if (shouldTreatAsBlob) {
|
|
1152
1205
|
return `[omitted:${value.length}]`;
|
|
1153
1206
|
}
|
|
1154
|
-
return truncateGenAiString(value, GEN_AI_MAX_STRING_CHARS);
|
|
1207
|
+
return truncateGenAiString(redactSecrets(value), GEN_AI_MAX_STRING_CHARS);
|
|
1155
1208
|
}
|
|
1156
1209
|
if (typeof value === "number") {
|
|
1157
1210
|
return Number.isFinite(value) ? value : void 0;
|
|
@@ -1166,7 +1219,7 @@ function sanitizeGenAiValue(value, seen, depth, keyName) {
|
|
|
1166
1219
|
return value.slice(0, GEN_AI_MAX_ARRAY_ITEMS).map((entry) => sanitizeGenAiValue(entry, seen, depth + 1)).filter((entry) => entry !== void 0);
|
|
1167
1220
|
}
|
|
1168
1221
|
if (typeof value !== "object") {
|
|
1169
|
-
return String(value);
|
|
1222
|
+
return redactSecrets(String(value));
|
|
1170
1223
|
}
|
|
1171
1224
|
if (seen.has(value)) {
|
|
1172
1225
|
return "[circular]";
|
|
@@ -1194,7 +1247,7 @@ function serializeGenAiAttribute(value, maxChars = GEN_AI_DEFAULT_MAX_ATTRIBUTE_
|
|
|
1194
1247
|
if (!serialized) {
|
|
1195
1248
|
return void 0;
|
|
1196
1249
|
}
|
|
1197
|
-
return truncateGenAiString(serialized, maxChars);
|
|
1250
|
+
return truncateGenAiString(redactSecrets(serialized), maxChars);
|
|
1198
1251
|
}
|
|
1199
1252
|
function asRecord(value) {
|
|
1200
1253
|
return value && typeof value === "object" ? value : void 0;
|
|
@@ -1270,6 +1323,125 @@ function extractGenAiUsageAttributes(...sources) {
|
|
|
1270
1323
|
// src/chat/plugins/manifest.ts
|
|
1271
1324
|
import { z } from "zod";
|
|
1272
1325
|
import { parse as parseYaml } from "yaml";
|
|
1326
|
+
|
|
1327
|
+
// src/chat/plugins/inline-manifest-source.ts
|
|
1328
|
+
function setDefined(target, key, value) {
|
|
1329
|
+
if (value !== void 0) {
|
|
1330
|
+
target[key] = value;
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
function isRecord2(value) {
|
|
1334
|
+
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
1335
|
+
}
|
|
1336
|
+
function unqualifyManifestToken(name, value) {
|
|
1337
|
+
if (typeof name === "string" && typeof value === "string" && value.startsWith(`${name}.`)) {
|
|
1338
|
+
return value.slice(name.length + 1);
|
|
1339
|
+
}
|
|
1340
|
+
return value;
|
|
1341
|
+
}
|
|
1342
|
+
function inlineTokenListSource(name, values) {
|
|
1343
|
+
if (values === void 0 || !Array.isArray(values)) {
|
|
1344
|
+
return values;
|
|
1345
|
+
}
|
|
1346
|
+
return values.map((value) => unqualifyManifestToken(name, value));
|
|
1347
|
+
}
|
|
1348
|
+
function inlineCredentialsSource(credentials) {
|
|
1349
|
+
if (credentials === void 0 || !isRecord2(credentials)) {
|
|
1350
|
+
return credentials;
|
|
1351
|
+
}
|
|
1352
|
+
const result = {};
|
|
1353
|
+
setDefined(result, "type", credentials.type);
|
|
1354
|
+
setDefined(result, "domains", credentials.domains);
|
|
1355
|
+
setDefined(result, "api-headers", credentials.apiHeaders);
|
|
1356
|
+
setDefined(result, "auth-token-env", credentials.authTokenEnv);
|
|
1357
|
+
setDefined(
|
|
1358
|
+
result,
|
|
1359
|
+
"auth-token-placeholder",
|
|
1360
|
+
credentials.authTokenPlaceholder
|
|
1361
|
+
);
|
|
1362
|
+
if (credentials.type === "github-app") {
|
|
1363
|
+
setDefined(result, "app-id-env", credentials.appIdEnv);
|
|
1364
|
+
setDefined(result, "private-key-env", credentials.privateKeyEnv);
|
|
1365
|
+
setDefined(result, "installation-id-env", credentials.installationIdEnv);
|
|
1366
|
+
}
|
|
1367
|
+
return result;
|
|
1368
|
+
}
|
|
1369
|
+
function inlineMcpSource(mcp) {
|
|
1370
|
+
if (mcp === void 0 || !isRecord2(mcp)) {
|
|
1371
|
+
return mcp;
|
|
1372
|
+
}
|
|
1373
|
+
const result = {};
|
|
1374
|
+
setDefined(result, "transport", mcp.transport);
|
|
1375
|
+
setDefined(result, "url", mcp.url);
|
|
1376
|
+
setDefined(result, "headers", mcp.headers);
|
|
1377
|
+
setDefined(result, "allowed-tools", mcp.allowedTools);
|
|
1378
|
+
return result;
|
|
1379
|
+
}
|
|
1380
|
+
function inlineOauthSource(oauth) {
|
|
1381
|
+
if (oauth === void 0 || !isRecord2(oauth)) {
|
|
1382
|
+
return oauth;
|
|
1383
|
+
}
|
|
1384
|
+
const result = {};
|
|
1385
|
+
setDefined(result, "client-id-env", oauth.clientIdEnv);
|
|
1386
|
+
setDefined(result, "client-secret-env", oauth.clientSecretEnv);
|
|
1387
|
+
setDefined(result, "authorize-endpoint", oauth.authorizeEndpoint);
|
|
1388
|
+
setDefined(result, "token-endpoint", oauth.tokenEndpoint);
|
|
1389
|
+
setDefined(result, "scope", oauth.scope);
|
|
1390
|
+
setDefined(result, "authorize-params", oauth.authorizeParams);
|
|
1391
|
+
setDefined(result, "token-auth-method", oauth.tokenAuthMethod);
|
|
1392
|
+
setDefined(result, "token-extra-headers", oauth.tokenExtraHeaders);
|
|
1393
|
+
return result;
|
|
1394
|
+
}
|
|
1395
|
+
function inlineTargetSource(name, target) {
|
|
1396
|
+
if (target === void 0 || !isRecord2(target)) {
|
|
1397
|
+
return target;
|
|
1398
|
+
}
|
|
1399
|
+
const result = {};
|
|
1400
|
+
setDefined(result, "type", target.type);
|
|
1401
|
+
setDefined(
|
|
1402
|
+
result,
|
|
1403
|
+
"config-key",
|
|
1404
|
+
unqualifyManifestToken(name, target.configKey)
|
|
1405
|
+
);
|
|
1406
|
+
setDefined(result, "command-flags", target.commandFlags);
|
|
1407
|
+
return result;
|
|
1408
|
+
}
|
|
1409
|
+
function inlineManifestSource(manifest) {
|
|
1410
|
+
const result = {};
|
|
1411
|
+
setDefined(result, "name", manifest.name);
|
|
1412
|
+
setDefined(result, "description", manifest.description);
|
|
1413
|
+
setDefined(
|
|
1414
|
+
result,
|
|
1415
|
+
"capabilities",
|
|
1416
|
+
inlineTokenListSource(manifest.name, manifest.capabilities)
|
|
1417
|
+
);
|
|
1418
|
+
setDefined(
|
|
1419
|
+
result,
|
|
1420
|
+
"config-keys",
|
|
1421
|
+
inlineTokenListSource(manifest.name, manifest.configKeys)
|
|
1422
|
+
);
|
|
1423
|
+
setDefined(result, "domains", manifest.domains);
|
|
1424
|
+
setDefined(result, "api-headers", manifest.apiHeaders);
|
|
1425
|
+
setDefined(result, "command-env", manifest.commandEnv);
|
|
1426
|
+
setDefined(result, "env-vars", manifest.envVars);
|
|
1427
|
+
setDefined(
|
|
1428
|
+
result,
|
|
1429
|
+
"credentials",
|
|
1430
|
+
inlineCredentialsSource(manifest.credentials)
|
|
1431
|
+
);
|
|
1432
|
+
setDefined(result, "runtime-dependencies", manifest.runtimeDependencies);
|
|
1433
|
+
setDefined(result, "runtime-postinstall", manifest.runtimePostinstall);
|
|
1434
|
+
setDefined(result, "mcp", inlineMcpSource(manifest.mcp));
|
|
1435
|
+
setDefined(result, "oauth", inlineOauthSource(manifest.oauth));
|
|
1436
|
+
setDefined(
|
|
1437
|
+
result,
|
|
1438
|
+
"target",
|
|
1439
|
+
inlineTargetSource(manifest.name, manifest.target)
|
|
1440
|
+
);
|
|
1441
|
+
return result;
|
|
1442
|
+
}
|
|
1443
|
+
|
|
1444
|
+
// src/chat/plugins/manifest.ts
|
|
1273
1445
|
var PLUGIN_NAME_RE = /^[a-z][a-z0-9-]*$/;
|
|
1274
1446
|
var SHORT_CAPABILITY_RE = /^[a-z0-9-]+(\.[a-z0-9-]+)*$/;
|
|
1275
1447
|
var SHORT_CONFIG_KEY_RE = /^[a-z0-9]+(\.[a-z0-9-]+)*$/;
|
|
@@ -1489,45 +1661,45 @@ var manifestSourceSchema = z.object({
|
|
|
1489
1661
|
error: "must be an object"
|
|
1490
1662
|
}).optional()
|
|
1491
1663
|
}).passthrough();
|
|
1492
|
-
function
|
|
1664
|
+
function setDefined2(target, key, value) {
|
|
1493
1665
|
if (value !== void 0) {
|
|
1494
1666
|
target[key] = value;
|
|
1495
1667
|
}
|
|
1496
1668
|
}
|
|
1497
1669
|
function manifestConfigPatch(config) {
|
|
1498
1670
|
const result = {};
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1671
|
+
setDefined2(result, "description", config.description);
|
|
1672
|
+
setDefined2(result, "capabilities", config.capabilities);
|
|
1673
|
+
setDefined2(result, "config-keys", config.configKeys);
|
|
1674
|
+
setDefined2(result, "domains", config.domains);
|
|
1675
|
+
setDefined2(result, "api-headers", config.apiHeaders);
|
|
1676
|
+
setDefined2(result, "command-env", config.commandEnv);
|
|
1677
|
+
setDefined2(result, "env-vars", config.envVars);
|
|
1506
1678
|
if (config.credentials !== void 0) {
|
|
1507
1679
|
if (!config.credentials) {
|
|
1508
1680
|
result.credentials = null;
|
|
1509
1681
|
} else {
|
|
1510
1682
|
const credentials = {};
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1683
|
+
setDefined2(credentials, "type", config.credentials.type);
|
|
1684
|
+
setDefined2(credentials, "domains", config.credentials.domains);
|
|
1685
|
+
setDefined2(credentials, "api-headers", config.credentials.apiHeaders);
|
|
1686
|
+
setDefined2(
|
|
1515
1687
|
credentials,
|
|
1516
1688
|
"auth-token-env",
|
|
1517
1689
|
config.credentials.authTokenEnv
|
|
1518
1690
|
);
|
|
1519
|
-
|
|
1691
|
+
setDefined2(
|
|
1520
1692
|
credentials,
|
|
1521
1693
|
"auth-token-placeholder",
|
|
1522
1694
|
config.credentials.authTokenPlaceholder
|
|
1523
1695
|
);
|
|
1524
|
-
|
|
1525
|
-
|
|
1696
|
+
setDefined2(credentials, "app-id-env", config.credentials.appIdEnv);
|
|
1697
|
+
setDefined2(
|
|
1526
1698
|
credentials,
|
|
1527
1699
|
"private-key-env",
|
|
1528
1700
|
config.credentials.privateKeyEnv
|
|
1529
1701
|
);
|
|
1530
|
-
|
|
1702
|
+
setDefined2(
|
|
1531
1703
|
credentials,
|
|
1532
1704
|
"installation-id-env",
|
|
1533
1705
|
config.credentials.installationIdEnv
|
|
@@ -1535,17 +1707,17 @@ function manifestConfigPatch(config) {
|
|
|
1535
1707
|
result.credentials = credentials;
|
|
1536
1708
|
}
|
|
1537
1709
|
}
|
|
1538
|
-
|
|
1539
|
-
|
|
1710
|
+
setDefined2(result, "runtime-dependencies", config.runtimeDependencies);
|
|
1711
|
+
setDefined2(result, "runtime-postinstall", config.runtimePostinstall);
|
|
1540
1712
|
if (config.mcp !== void 0) {
|
|
1541
1713
|
if (!config.mcp) {
|
|
1542
1714
|
result.mcp = null;
|
|
1543
1715
|
} else {
|
|
1544
1716
|
const mcp = {};
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1717
|
+
setDefined2(mcp, "transport", config.mcp.transport);
|
|
1718
|
+
setDefined2(mcp, "url", config.mcp.url);
|
|
1719
|
+
setDefined2(mcp, "headers", config.mcp.headers);
|
|
1720
|
+
setDefined2(mcp, "allowed-tools", config.mcp.allowedTools);
|
|
1549
1721
|
result.mcp = mcp;
|
|
1550
1722
|
}
|
|
1551
1723
|
}
|
|
@@ -1554,14 +1726,14 @@ function manifestConfigPatch(config) {
|
|
|
1554
1726
|
result.oauth = null;
|
|
1555
1727
|
} else {
|
|
1556
1728
|
const oauth = {};
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1729
|
+
setDefined2(oauth, "client-id-env", config.oauth.clientIdEnv);
|
|
1730
|
+
setDefined2(oauth, "client-secret-env", config.oauth.clientSecretEnv);
|
|
1731
|
+
setDefined2(oauth, "authorize-endpoint", config.oauth.authorizeEndpoint);
|
|
1732
|
+
setDefined2(oauth, "token-endpoint", config.oauth.tokenEndpoint);
|
|
1733
|
+
setDefined2(oauth, "scope", config.oauth.scope);
|
|
1734
|
+
setDefined2(oauth, "authorize-params", config.oauth.authorizeParams);
|
|
1735
|
+
setDefined2(oauth, "token-auth-method", config.oauth.tokenAuthMethod);
|
|
1736
|
+
setDefined2(oauth, "token-extra-headers", config.oauth.tokenExtraHeaders);
|
|
1565
1737
|
result.oauth = oauth;
|
|
1566
1738
|
}
|
|
1567
1739
|
}
|
|
@@ -1570,9 +1742,9 @@ function manifestConfigPatch(config) {
|
|
|
1570
1742
|
result.target = null;
|
|
1571
1743
|
} else {
|
|
1572
1744
|
const target = {};
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1745
|
+
setDefined2(target, "type", config.target.type);
|
|
1746
|
+
setDefined2(target, "config-key", config.target.configKey);
|
|
1747
|
+
setDefined2(target, "command-flags", config.target.commandFlags);
|
|
1576
1748
|
result.target = target;
|
|
1577
1749
|
}
|
|
1578
1750
|
}
|
|
@@ -1741,6 +1913,21 @@ function assertCommandEnvDoesNotExposeHostSecretRefs(commandEnv, apiHeaders, cre
|
|
|
1741
1913
|
}
|
|
1742
1914
|
}
|
|
1743
1915
|
}
|
|
1916
|
+
function assertCommandEnvHostRefsAreExplicitlyExposed(commandEnv, envVars, pluginName) {
|
|
1917
|
+
if (!commandEnv) {
|
|
1918
|
+
return;
|
|
1919
|
+
}
|
|
1920
|
+
for (const [key, value] of Object.entries(commandEnv)) {
|
|
1921
|
+
for (const name of envReferences(value)) {
|
|
1922
|
+
const declaration = envVars[name];
|
|
1923
|
+
if (declaration && declaration.default === void 0 && declaration.exposeToCommandEnv !== true) {
|
|
1924
|
+
throw new Error(
|
|
1925
|
+
`Plugin ${pluginName} command-env.${key} references env var ${name}, but env-vars.${name} must set expose-to-command-env: true before host env can be exposed to sandbox`
|
|
1926
|
+
);
|
|
1927
|
+
}
|
|
1928
|
+
}
|
|
1929
|
+
}
|
|
1930
|
+
}
|
|
1744
1931
|
function normalizeCredentials(data, name) {
|
|
1745
1932
|
const schema = data.type === "oauth-bearer" ? oauthBearerCredentialsSchema : data.type === "github-app" ? githubAppCredentialsSchema : void 0;
|
|
1746
1933
|
if (!schema) {
|
|
@@ -1915,7 +2102,9 @@ function normalizeRuntimePostinstall(commands, name) {
|
|
|
1915
2102
|
var envVarDeclarationSchema = z.preprocess(
|
|
1916
2103
|
(value) => value === null || value === void 0 ? {} : value,
|
|
1917
2104
|
z.object({
|
|
1918
|
-
default: z.string().optional()
|
|
2105
|
+
default: z.string().optional(),
|
|
2106
|
+
"expose-to-command-env": z.boolean().optional(),
|
|
2107
|
+
exposeToCommandEnv: z.boolean().optional()
|
|
1919
2108
|
}).strict()
|
|
1920
2109
|
);
|
|
1921
2110
|
function normalizeEnvVars(data, pluginName) {
|
|
@@ -1937,6 +2126,9 @@ function normalizeEnvVars(data, pluginName) {
|
|
|
1937
2126
|
if (parsed.data.default !== void 0) {
|
|
1938
2127
|
decl.default = parsed.data.default;
|
|
1939
2128
|
}
|
|
2129
|
+
if (parsed.data["expose-to-command-env"] === true || parsed.data.exposeToCommandEnv === true) {
|
|
2130
|
+
decl.exposeToCommandEnv = true;
|
|
2131
|
+
}
|
|
1940
2132
|
normalized[name] = decl;
|
|
1941
2133
|
}
|
|
1942
2134
|
return normalized;
|
|
@@ -1985,89 +2177,76 @@ function normalizeMcp(data, envVars, name) {
|
|
|
1985
2177
|
...result.data["allowed-tools"] ? { allowedTools: result.data["allowed-tools"] } : {}
|
|
1986
2178
|
};
|
|
1987
2179
|
}
|
|
1988
|
-
function
|
|
1989
|
-
|
|
1990
|
-
try {
|
|
1991
|
-
parsedYaml = parseYaml(raw);
|
|
1992
|
-
} catch (error) {
|
|
1993
|
-
throw new Error(
|
|
1994
|
-
`Invalid plugin manifest in ${dir}: ${error instanceof Error ? error.message : String(error)}`
|
|
1995
|
-
);
|
|
1996
|
-
}
|
|
1997
|
-
if (!parsedYaml || typeof parsedYaml !== "object" || Array.isArray(parsedYaml)) {
|
|
1998
|
-
throw new Error(`Invalid plugin manifest in ${dir}: expected an object`);
|
|
1999
|
-
}
|
|
2000
|
-
const source = applyManifestConfig(parsedYaml, config);
|
|
2180
|
+
function parseManifestSource(parsedSource, dir, config) {
|
|
2181
|
+
const source = applyManifestConfig(parsedSource, config);
|
|
2001
2182
|
const sourceResult = manifestSourceSchema.safeParse(source);
|
|
2002
2183
|
if (!sourceResult.success) {
|
|
2003
2184
|
const issue = sourceResult.error.issues[0];
|
|
2004
2185
|
const path3 = formatPath(issue?.path ?? []);
|
|
2005
2186
|
if (path3 === "name") {
|
|
2006
|
-
throw new Error(
|
|
2007
|
-
`Invalid plugin name in ${dir}: "${parsedYaml.name}"`
|
|
2008
|
-
);
|
|
2187
|
+
throw new Error(`Invalid plugin name in ${dir}: "${parsedSource.name}"`);
|
|
2009
2188
|
}
|
|
2010
2189
|
if (path3 === "description") {
|
|
2011
2190
|
throw new Error(`Invalid plugin description in ${dir}`);
|
|
2012
2191
|
}
|
|
2013
2192
|
if (path3 === "capabilities") {
|
|
2014
2193
|
throw new Error(
|
|
2015
|
-
`Plugin ${
|
|
2194
|
+
`Plugin ${String(parsedSource.name ?? "unknown")} capabilities must be an array when provided`
|
|
2016
2195
|
);
|
|
2017
2196
|
}
|
|
2018
2197
|
if (path3 === "config-keys") {
|
|
2019
2198
|
throw new Error(
|
|
2020
|
-
`Plugin ${
|
|
2199
|
+
`Plugin ${String(parsedSource.name ?? "unknown")} config-keys must be an array when provided`
|
|
2021
2200
|
);
|
|
2022
2201
|
}
|
|
2023
2202
|
if (path3 === "domains") {
|
|
2024
2203
|
throw new Error(
|
|
2025
|
-
`Plugin ${
|
|
2204
|
+
`Plugin ${String(parsedSource.name ?? "unknown")} ${path3} must be a non-empty array of domains`
|
|
2026
2205
|
);
|
|
2027
2206
|
}
|
|
2028
2207
|
if (path3 === "api-headers") {
|
|
2029
2208
|
throw new Error(
|
|
2030
|
-
`Plugin ${
|
|
2209
|
+
`Plugin ${String(parsedSource.name ?? "unknown")} api-headers must be an object when provided`
|
|
2031
2210
|
);
|
|
2032
2211
|
}
|
|
2033
2212
|
if (path3 === "command-env") {
|
|
2034
2213
|
throw new Error(
|
|
2035
|
-
`Plugin ${
|
|
2214
|
+
`Plugin ${String(parsedSource.name ?? "unknown")} command-env must be an object when provided`
|
|
2036
2215
|
);
|
|
2037
2216
|
}
|
|
2038
2217
|
if (path3 === "credentials") {
|
|
2039
2218
|
throw new Error(
|
|
2040
|
-
`Plugin ${
|
|
2219
|
+
`Plugin ${String(parsedSource.name ?? "unknown")} credentials must be an object when provided`
|
|
2041
2220
|
);
|
|
2042
2221
|
}
|
|
2043
2222
|
if (path3 === "runtime-dependencies") {
|
|
2044
2223
|
throw new Error(
|
|
2045
|
-
`Plugin ${
|
|
2224
|
+
`Plugin ${String(parsedSource.name ?? "unknown")} runtime-dependencies must be an array`
|
|
2046
2225
|
);
|
|
2047
2226
|
}
|
|
2048
2227
|
if (path3 === "runtime-postinstall") {
|
|
2049
2228
|
throw new Error(
|
|
2050
|
-
`Plugin ${
|
|
2229
|
+
`Plugin ${String(parsedSource.name ?? "unknown")} runtime-postinstall must be an array`
|
|
2051
2230
|
);
|
|
2052
2231
|
}
|
|
2053
2232
|
if (path3 === "env-vars") {
|
|
2054
2233
|
throw new Error(
|
|
2055
|
-
`Plugin ${
|
|
2234
|
+
`Plugin ${String(parsedSource.name ?? "unknown")} env-vars must be an object`
|
|
2056
2235
|
);
|
|
2057
2236
|
}
|
|
2058
2237
|
if (path3 === "mcp") {
|
|
2059
2238
|
throw new Error(
|
|
2060
|
-
`Plugin ${
|
|
2239
|
+
`Plugin ${String(parsedSource.name ?? "unknown")} mcp must be an object`
|
|
2061
2240
|
);
|
|
2062
2241
|
}
|
|
2063
2242
|
if (path3 === "oauth") {
|
|
2064
2243
|
throw new Error(
|
|
2065
|
-
`Plugin ${
|
|
2244
|
+
`Plugin ${String(parsedSource.name ?? "unknown")} oauth must be an object`
|
|
2066
2245
|
);
|
|
2067
2246
|
}
|
|
2068
2247
|
if (path3 === "target") {
|
|
2069
2248
|
throw new Error(
|
|
2070
|
-
`Plugin ${
|
|
2249
|
+
`Plugin ${String(parsedSource.name ?? "unknown")} target must be an object`
|
|
2071
2250
|
);
|
|
2072
2251
|
}
|
|
2073
2252
|
throw new Error(issue?.message ?? `Invalid plugin manifest in ${dir}`);
|
|
@@ -2108,11 +2287,6 @@ function parsePluginManifest(raw, dir, config) {
|
|
|
2108
2287
|
envVars
|
|
2109
2288
|
) : void 0;
|
|
2110
2289
|
const credentials = data.credentials ? normalizeCredentials(data.credentials, data.name) : void 0;
|
|
2111
|
-
if (commandEnv && !credentials && !apiHeaders) {
|
|
2112
|
-
throw new Error(
|
|
2113
|
-
`Plugin ${data.name} command-env requires credentials or api-headers`
|
|
2114
|
-
);
|
|
2115
|
-
}
|
|
2116
2290
|
const runtimeDependencies = data["runtime-dependencies"] ? normalizeRuntimeDependencies(data["runtime-dependencies"], data.name) : void 0;
|
|
2117
2291
|
const runtimePostinstall = data["runtime-postinstall"] ? normalizeRuntimePostinstall(data["runtime-postinstall"], data.name) : void 0;
|
|
2118
2292
|
const mcp = data.mcp ? normalizeMcp(data.mcp, envVars, data.name) : void 0;
|
|
@@ -2175,6 +2349,11 @@ function parsePluginManifest(raw, dir, config) {
|
|
|
2175
2349
|
manifest.oauth,
|
|
2176
2350
|
data.name
|
|
2177
2351
|
);
|
|
2352
|
+
assertCommandEnvHostRefsAreExplicitlyExposed(
|
|
2353
|
+
data["command-env"],
|
|
2354
|
+
envVars,
|
|
2355
|
+
data.name
|
|
2356
|
+
);
|
|
2178
2357
|
if (data.target) {
|
|
2179
2358
|
const result = targetSourceSchema.safeParse(data.target);
|
|
2180
2359
|
if (!result.success) {
|
|
@@ -2205,6 +2384,23 @@ function parsePluginManifest(raw, dir, config) {
|
|
|
2205
2384
|
}
|
|
2206
2385
|
return manifest;
|
|
2207
2386
|
}
|
|
2387
|
+
function parsePluginManifest(raw, dir, config) {
|
|
2388
|
+
let parsedYaml;
|
|
2389
|
+
try {
|
|
2390
|
+
parsedYaml = parseYaml(raw);
|
|
2391
|
+
} catch (error) {
|
|
2392
|
+
throw new Error(
|
|
2393
|
+
`Invalid plugin manifest in ${dir}: ${error instanceof Error ? error.message : String(error)}`
|
|
2394
|
+
);
|
|
2395
|
+
}
|
|
2396
|
+
if (!parsedYaml || typeof parsedYaml !== "object" || Array.isArray(parsedYaml)) {
|
|
2397
|
+
throw new Error(`Invalid plugin manifest in ${dir}: expected an object`);
|
|
2398
|
+
}
|
|
2399
|
+
return parseManifestSource(parsedYaml, dir, config);
|
|
2400
|
+
}
|
|
2401
|
+
function parseInlinePluginManifest(manifest, dir, config) {
|
|
2402
|
+
return parseManifestSource(inlineManifestSource(manifest), dir, config);
|
|
2403
|
+
}
|
|
2208
2404
|
|
|
2209
2405
|
// src/chat/plugins/registry.ts
|
|
2210
2406
|
import { readFileSync, readdirSync, statSync } from "fs";
|
|
@@ -2852,8 +3048,7 @@ function providerDomains(manifest) {
|
|
|
2852
3048
|
])
|
|
2853
3049
|
].sort((left, right) => left.localeCompare(right));
|
|
2854
3050
|
}
|
|
2855
|
-
function registerPluginManifest(state,
|
|
2856
|
-
const manifest = parsePluginManifest(raw, pluginDir, pluginConfig);
|
|
3051
|
+
function registerPluginManifest(state, manifest, pluginDir, skillsDir) {
|
|
2857
3052
|
if (state.pluginsByName.has(manifest.name)) {
|
|
2858
3053
|
throw new Error(`Duplicate plugin name "${manifest.name}"`);
|
|
2859
3054
|
}
|
|
@@ -2868,14 +3063,14 @@ function registerPluginManifest(state, raw, pluginDir) {
|
|
|
2868
3063
|
const owner = state.domainToPlugin.get(domain);
|
|
2869
3064
|
if (owner) {
|
|
2870
3065
|
throw new Error(
|
|
2871
|
-
`Duplicate provider domain "${domain}" in plugin "${manifest.name}" already declared by plugin "${owner}". Use plugins.manifests in
|
|
3066
|
+
`Duplicate provider domain "${domain}" in plugin "${manifest.name}" already declared by plugin "${owner}". Use plugins.manifests in PluginCatalogConfig to change one plugin's domains or credentials.`
|
|
2872
3067
|
);
|
|
2873
3068
|
}
|
|
2874
3069
|
}
|
|
2875
3070
|
const definition = {
|
|
2876
3071
|
manifest,
|
|
2877
3072
|
dir: pluginDir,
|
|
2878
|
-
skillsDir:
|
|
3073
|
+
...skillsDir ? { skillsDir } : {}
|
|
2879
3074
|
};
|
|
2880
3075
|
state.pluginDefinitions.push(definition);
|
|
2881
3076
|
state.pluginsByName.set(manifest.name, definition);
|
|
@@ -2889,6 +3084,15 @@ function registerPluginManifest(state, raw, pluginDir) {
|
|
|
2889
3084
|
state.domainToPlugin.set(domain, manifest.name);
|
|
2890
3085
|
}
|
|
2891
3086
|
}
|
|
3087
|
+
function registerYamlPluginManifest(state, raw, pluginDir) {
|
|
3088
|
+
const manifest = parsePluginManifest(raw, pluginDir, pluginConfig);
|
|
3089
|
+
registerPluginManifest(
|
|
3090
|
+
state,
|
|
3091
|
+
manifest,
|
|
3092
|
+
pluginDir,
|
|
3093
|
+
path2.join(pluginDir, "skills")
|
|
3094
|
+
);
|
|
3095
|
+
}
|
|
2892
3096
|
function normalizePluginRoots(roots) {
|
|
2893
3097
|
const resolved = [];
|
|
2894
3098
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -2910,10 +3114,14 @@ function getPluginCatalogSource() {
|
|
|
2910
3114
|
...packagedContent.manifestRoots
|
|
2911
3115
|
]);
|
|
2912
3116
|
const packagedSkillRoots = normalizePluginRoots(packagedContent.skillRoots);
|
|
3117
|
+
const inlineManifests = pluginConfig?.inlineManifests ?? [];
|
|
2913
3118
|
return {
|
|
3119
|
+
inlineManifests,
|
|
2914
3120
|
manifestRoots,
|
|
2915
3121
|
packagedSkillRoots,
|
|
3122
|
+
packagedContent,
|
|
2916
3123
|
signature: JSON.stringify({
|
|
3124
|
+
inlineManifests,
|
|
2917
3125
|
manifestRoots,
|
|
2918
3126
|
packagedSkillRoots,
|
|
2919
3127
|
packageNames: [...packagedContent.packageNames].sort(),
|
|
@@ -2921,24 +3129,42 @@ function getPluginCatalogSource() {
|
|
|
2921
3129
|
})
|
|
2922
3130
|
};
|
|
2923
3131
|
}
|
|
2924
|
-
function
|
|
3132
|
+
function normalizePluginCatalogConfig(config) {
|
|
2925
3133
|
if (!config) {
|
|
2926
3134
|
return void 0;
|
|
2927
3135
|
}
|
|
2928
3136
|
return {
|
|
3137
|
+
inlineManifests: config.inlineManifests ? structuredClone(config.inlineManifests) : void 0,
|
|
2929
3138
|
packages: normalizePluginPackageNames(config.packages),
|
|
2930
3139
|
...config.manifests ? { manifests: structuredClone(config.manifests) } : {}
|
|
2931
3140
|
};
|
|
2932
3141
|
}
|
|
2933
|
-
function
|
|
3142
|
+
function clonePluginCatalogConfig(config) {
|
|
2934
3143
|
if (!config) {
|
|
2935
3144
|
return void 0;
|
|
2936
3145
|
}
|
|
2937
3146
|
return {
|
|
3147
|
+
...config.inlineManifests ? { inlineManifests: structuredClone(config.inlineManifests) } : {},
|
|
2938
3148
|
packages: [...config.packages ?? []],
|
|
2939
3149
|
...config.manifests ? { manifests: structuredClone(config.manifests) } : {}
|
|
2940
3150
|
};
|
|
2941
3151
|
}
|
|
3152
|
+
function packageContentByName(packagedContent, packageName) {
|
|
3153
|
+
return packagedContent.packages.find((pkg) => pkg.name === packageName);
|
|
3154
|
+
}
|
|
3155
|
+
function registerInlineManifests(state, source) {
|
|
3156
|
+
for (const definition of source.inlineManifests) {
|
|
3157
|
+
const pkg = definition.packageName ? packageContentByName(source.packagedContent, definition.packageName) : void 0;
|
|
3158
|
+
const dir = pkg?.dir ?? process.cwd();
|
|
3159
|
+
const skillsDir = pkg?.hasSkillsDir ? path2.join(pkg.dir, "skills") : void 0;
|
|
3160
|
+
const manifest = parseInlinePluginManifest(
|
|
3161
|
+
definition.manifest,
|
|
3162
|
+
dir,
|
|
3163
|
+
pluginConfig
|
|
3164
|
+
);
|
|
3165
|
+
registerPluginManifest(state, manifest, dir, skillsDir);
|
|
3166
|
+
}
|
|
3167
|
+
}
|
|
2942
3168
|
function discoverConfiguredPluginPackageContent() {
|
|
2943
3169
|
return discoverInstalledPluginPackageContent(process.cwd(), {
|
|
2944
3170
|
packageNames: pluginConfig?.packages
|
|
@@ -2949,6 +3175,7 @@ function buildLoadedPluginState(source) {
|
|
|
2949
3175
|
for (const skillRoot of source.packagedSkillRoots) {
|
|
2950
3176
|
state.packageSkillRoots.add(skillRoot);
|
|
2951
3177
|
}
|
|
3178
|
+
registerInlineManifests(state, source);
|
|
2952
3179
|
const roots = source.manifestRoots;
|
|
2953
3180
|
for (const pluginsRoot of roots) {
|
|
2954
3181
|
let entries;
|
|
@@ -2977,7 +3204,7 @@ function buildLoadedPluginState(source) {
|
|
|
2977
3204
|
}
|
|
2978
3205
|
if (hasRootManifest) {
|
|
2979
3206
|
const rawRootManifest = readFileSync(manifestPath, "utf8");
|
|
2980
|
-
|
|
3207
|
+
registerYamlPluginManifest(state, rawRootManifest, pluginsRoot);
|
|
2981
3208
|
continue;
|
|
2982
3209
|
}
|
|
2983
3210
|
}
|
|
@@ -3010,7 +3237,7 @@ function buildLoadedPluginState(source) {
|
|
|
3010
3237
|
} catch {
|
|
3011
3238
|
continue;
|
|
3012
3239
|
}
|
|
3013
|
-
|
|
3240
|
+
registerYamlPluginManifest(state, raw, pluginDir);
|
|
3014
3241
|
}
|
|
3015
3242
|
}
|
|
3016
3243
|
for (const name of Object.keys(pluginConfig?.manifests ?? {})) {
|
|
@@ -3040,7 +3267,7 @@ function logLoadedPlugins(state) {
|
|
|
3040
3267
|
"app.plugin.config_key_count": plugin.manifest.configKeys.length,
|
|
3041
3268
|
"app.plugin.has_mcp": Boolean(plugin.manifest.mcp),
|
|
3042
3269
|
"file.directory": plugin.dir,
|
|
3043
|
-
"app.file.skill_directory": plugin.skillsDir
|
|
3270
|
+
...plugin.skillsDir ? { "app.file.skill_directory": plugin.skillsDir } : {}
|
|
3044
3271
|
},
|
|
3045
3272
|
"Loaded plugin"
|
|
3046
3273
|
);
|
|
@@ -3056,9 +3283,9 @@ function ensurePluginsLoaded() {
|
|
|
3056
3283
|
logLoadedPlugins(state);
|
|
3057
3284
|
return state;
|
|
3058
3285
|
}
|
|
3059
|
-
function
|
|
3060
|
-
const previousConfig =
|
|
3061
|
-
pluginConfig =
|
|
3286
|
+
function setPluginCatalogConfig(config) {
|
|
3287
|
+
const previousConfig = clonePluginCatalogConfig(pluginConfig);
|
|
3288
|
+
pluginConfig = normalizePluginCatalogConfig(config);
|
|
3062
3289
|
return previousConfig;
|
|
3063
3290
|
}
|
|
3064
3291
|
function getPluginPackageContent() {
|
|
@@ -3152,7 +3379,9 @@ function getPluginSkillRoots() {
|
|
|
3152
3379
|
const state = ensurePluginsLoaded();
|
|
3153
3380
|
return [
|
|
3154
3381
|
.../* @__PURE__ */ new Set([
|
|
3155
|
-
...state.pluginDefinitions.
|
|
3382
|
+
...state.pluginDefinitions.flatMap(
|
|
3383
|
+
(plugin) => plugin.skillsDir ? [plugin.skillsDir] : []
|
|
3384
|
+
),
|
|
3156
3385
|
...state.packageSkillRoots
|
|
3157
3386
|
])
|
|
3158
3387
|
];
|
|
@@ -3161,6 +3390,9 @@ function getPluginForSkillPath(skillPath) {
|
|
|
3161
3390
|
const state = ensurePluginsLoaded();
|
|
3162
3391
|
const resolvedSkillPath = path2.resolve(skillPath);
|
|
3163
3392
|
return state.pluginDefinitions.find((plugin) => {
|
|
3393
|
+
if (!plugin.skillsDir) {
|
|
3394
|
+
return false;
|
|
3395
|
+
}
|
|
3164
3396
|
const resolvedSkillsDir = path2.resolve(plugin.skillsDir);
|
|
3165
3397
|
return resolvedSkillPath === resolvedSkillsDir || resolvedSkillPath.startsWith(`${resolvedSkillsDir}${path2.sep}`);
|
|
3166
3398
|
});
|
|
@@ -3210,6 +3442,7 @@ export {
|
|
|
3210
3442
|
normalizeGenAiFinishReason,
|
|
3211
3443
|
createChatSdkLogger,
|
|
3212
3444
|
getLogContextAttributes,
|
|
3445
|
+
setSentryUser,
|
|
3213
3446
|
logInfo,
|
|
3214
3447
|
logWarn,
|
|
3215
3448
|
logError,
|
|
@@ -3232,7 +3465,7 @@ export {
|
|
|
3232
3465
|
hasRequiredOAuthScope,
|
|
3233
3466
|
buildOAuthTokenRequest,
|
|
3234
3467
|
parseOAuthTokenResponse,
|
|
3235
|
-
|
|
3468
|
+
setPluginCatalogConfig,
|
|
3236
3469
|
getPluginPackageContent,
|
|
3237
3470
|
getPluginCatalogSignature,
|
|
3238
3471
|
getPluginCapabilityProviders,
|