@sentry/junior 0.33.0 → 0.35.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 +923 -722
- package/dist/{chunk-3M7ZD6FF.js → chunk-ERH4OYNB.js} +92 -56
- package/dist/{chunk-EHXMTKBA.js → chunk-LAD5O3RX.js} +1 -1
- package/dist/{chunk-XARRBRQV.js → chunk-QZRPUFO6.js} +202 -62
- package/dist/cli/check.js +2 -2
- package/dist/cli/snapshot-warmup.js +2 -2
- package/package.json +3 -3
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
serializeGenAiAttribute,
|
|
8
8
|
setSpanAttributes,
|
|
9
9
|
withSpan
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-QZRPUFO6.js";
|
|
11
11
|
|
|
12
12
|
// src/chat/state/adapter.ts
|
|
13
13
|
import { createMemoryState } from "@chat-adapter/state-memory";
|
|
@@ -128,68 +128,73 @@ async function completeText(params) {
|
|
|
128
128
|
const apiKey = getPiGatewayApiKeyOverride();
|
|
129
129
|
const requestMessagesAttribute = serializeGenAiAttribute(params.messages);
|
|
130
130
|
const systemInstructionsAttribute = params.system ? serializeGenAiAttribute([{ type: "text", content: params.system }]) : void 0;
|
|
131
|
-
const
|
|
131
|
+
const baseAttributes = {
|
|
132
132
|
"gen_ai.provider.name": GEN_AI_PROVIDER_NAME,
|
|
133
133
|
"gen_ai.operation.name": GEN_AI_OPERATION_CHAT,
|
|
134
134
|
"gen_ai.request.model": params.modelId,
|
|
135
|
+
...params.thinkingLevel ? { "app.ai.reasoning_effort": params.thinkingLevel } : {}
|
|
136
|
+
};
|
|
137
|
+
const startAttributes = {
|
|
138
|
+
...baseAttributes,
|
|
135
139
|
...systemInstructionsAttribute ? { "gen_ai.system_instructions": systemInstructionsAttribute } : {},
|
|
136
140
|
...requestMessagesAttribute ? { "gen_ai.input.messages": requestMessagesAttribute } : {},
|
|
137
|
-
"app.ai.auth_mode": apiKey ? "oidc" : "api_key"
|
|
138
|
-
...params.thinkingLevel ? { "app.ai.reasoning_effort": params.thinkingLevel } : {}
|
|
141
|
+
"app.ai.auth_mode": apiKey ? "oidc" : "api_key"
|
|
139
142
|
};
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
{
|
|
144
|
-
|
|
145
|
-
|
|
143
|
+
return withSpan(
|
|
144
|
+
"ai.chat_completion",
|
|
145
|
+
"gen_ai.chat",
|
|
146
|
+
{ modelId: params.modelId },
|
|
147
|
+
async () => {
|
|
148
|
+
const message = await completeSimple(
|
|
149
|
+
model,
|
|
150
|
+
{
|
|
151
|
+
systemPrompt: params.system,
|
|
152
|
+
messages: params.messages
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
...apiKey ? { apiKey } : {},
|
|
156
|
+
temperature: params.temperature,
|
|
157
|
+
maxTokens: params.maxTokens,
|
|
158
|
+
reasoning: params.thinkingLevel,
|
|
159
|
+
signal: params.signal,
|
|
160
|
+
metadata: params.metadata
|
|
161
|
+
}
|
|
162
|
+
);
|
|
163
|
+
const outputText = extractText(message);
|
|
164
|
+
const outputMessagesAttribute = serializeGenAiAttribute([
|
|
165
|
+
{
|
|
166
|
+
role: "assistant",
|
|
167
|
+
content: outputText ? [{ type: "text", text: outputText }] : []
|
|
168
|
+
}
|
|
169
|
+
]);
|
|
170
|
+
const usageAttributes = extractGenAiUsageAttributes(message);
|
|
171
|
+
const endAttributes = {
|
|
172
|
+
...baseAttributes,
|
|
173
|
+
...outputMessagesAttribute ? { "gen_ai.output.messages": outputMessagesAttribute } : {},
|
|
174
|
+
...usageAttributes,
|
|
175
|
+
...message.stopReason ? { "gen_ai.response.finish_reasons": [message.stopReason] } : {}
|
|
176
|
+
};
|
|
177
|
+
setSpanAttributes(endAttributes);
|
|
178
|
+
if (message.stopReason === "error") {
|
|
179
|
+
const providerMessage = message.errorMessage?.trim() || "Unknown provider error";
|
|
180
|
+
logWarn(
|
|
181
|
+
"ai_completion_provider_error",
|
|
182
|
+
{},
|
|
183
|
+
{
|
|
184
|
+
...baseAttributes,
|
|
185
|
+
"error.message": providerMessage
|
|
186
|
+
},
|
|
187
|
+
"AI completion returned provider error"
|
|
188
|
+
);
|
|
189
|
+
throw new Error(`AI provider error: ${providerMessage}`);
|
|
190
|
+
}
|
|
191
|
+
return {
|
|
192
|
+
message,
|
|
193
|
+
text: outputText
|
|
194
|
+
};
|
|
146
195
|
},
|
|
147
|
-
|
|
148
|
-
...apiKey ? { apiKey } : {},
|
|
149
|
-
temperature: params.temperature,
|
|
150
|
-
maxTokens: params.maxTokens,
|
|
151
|
-
reasoning: params.thinkingLevel,
|
|
152
|
-
signal: params.signal,
|
|
153
|
-
metadata: params.metadata
|
|
154
|
-
}
|
|
196
|
+
startAttributes
|
|
155
197
|
);
|
|
156
|
-
const outputText = extractText(message);
|
|
157
|
-
const outputMessagesAttribute = serializeGenAiAttribute([
|
|
158
|
-
{
|
|
159
|
-
role: "assistant",
|
|
160
|
-
content: outputText ? [{ type: "text", text: outputText }] : []
|
|
161
|
-
}
|
|
162
|
-
]);
|
|
163
|
-
const usageAttributes = extractGenAiUsageAttributes(message);
|
|
164
|
-
const endAttributes = {
|
|
165
|
-
"gen_ai.provider.name": GEN_AI_PROVIDER_NAME,
|
|
166
|
-
"gen_ai.operation.name": GEN_AI_OPERATION_CHAT,
|
|
167
|
-
"gen_ai.request.model": params.modelId,
|
|
168
|
-
...outputMessagesAttribute ? { "gen_ai.output.messages": outputMessagesAttribute } : {},
|
|
169
|
-
...usageAttributes,
|
|
170
|
-
...message.stopReason ? { "gen_ai.response.finish_reasons": [message.stopReason] } : {},
|
|
171
|
-
...params.thinkingLevel ? { "app.ai.reasoning_effort": params.thinkingLevel } : {}
|
|
172
|
-
};
|
|
173
|
-
setSpanAttributes(endAttributes);
|
|
174
|
-
if (message.stopReason === "error") {
|
|
175
|
-
const providerMessage = message.errorMessage?.trim() || "Unknown provider error";
|
|
176
|
-
logWarn(
|
|
177
|
-
"ai_completion_provider_error",
|
|
178
|
-
{},
|
|
179
|
-
{
|
|
180
|
-
"gen_ai.provider.name": GEN_AI_PROVIDER_NAME,
|
|
181
|
-
"gen_ai.operation.name": GEN_AI_OPERATION_CHAT,
|
|
182
|
-
"gen_ai.request.model": params.modelId,
|
|
183
|
-
"error.message": providerMessage
|
|
184
|
-
},
|
|
185
|
-
"AI completion returned provider error"
|
|
186
|
-
);
|
|
187
|
-
throw new Error(`AI provider error: ${providerMessage}`);
|
|
188
|
-
}
|
|
189
|
-
return {
|
|
190
|
-
message,
|
|
191
|
-
text: outputText
|
|
192
|
-
};
|
|
193
198
|
}
|
|
194
199
|
async function completeObject(params) {
|
|
195
200
|
const startedAt = Date.now();
|
|
@@ -256,6 +261,14 @@ async function completeObject(params) {
|
|
|
256
261
|
var MIN_AGENT_TURN_TIMEOUT_MS = 10 * 1e3;
|
|
257
262
|
var DEFAULT_AGENT_TURN_TIMEOUT_MS = 12 * 60 * 1e3;
|
|
258
263
|
var DEFAULT_FUNCTION_MAX_DURATION_SECONDS = 800;
|
|
264
|
+
var ADVISOR_THINKING_LEVELS = [
|
|
265
|
+
"minimal",
|
|
266
|
+
"low",
|
|
267
|
+
"medium",
|
|
268
|
+
"high",
|
|
269
|
+
"xhigh"
|
|
270
|
+
];
|
|
271
|
+
var DEFAULT_ADVISOR_THINKING_LEVEL = "xhigh";
|
|
259
272
|
var FUNCTION_TIMEOUT_BUFFER_SECONDS = 20;
|
|
260
273
|
var DEFAULT_ASSISTANT_LOADING_MESSAGES = [
|
|
261
274
|
"Consulting the orb",
|
|
@@ -314,17 +327,39 @@ function parseLoadingMessages(rawValue) {
|
|
|
314
327
|
return value.trim();
|
|
315
328
|
});
|
|
316
329
|
}
|
|
330
|
+
function parseAdvisorThinkingLevel(rawValue) {
|
|
331
|
+
const value = toOptionalTrimmed(rawValue);
|
|
332
|
+
if (!value) {
|
|
333
|
+
return DEFAULT_ADVISOR_THINKING_LEVEL;
|
|
334
|
+
}
|
|
335
|
+
if (ADVISOR_THINKING_LEVELS.includes(value)) {
|
|
336
|
+
return value;
|
|
337
|
+
}
|
|
338
|
+
throw new Error(
|
|
339
|
+
`AI_ADVISOR_THINKING_LEVEL must be one of: minimal, low, medium, high, xhigh`
|
|
340
|
+
);
|
|
341
|
+
}
|
|
317
342
|
var DEFAULT_MODEL_ID = getModel("vercel-ai-gateway", "openai/gpt-5.4").id;
|
|
318
343
|
var DEFAULT_FAST_MODEL_ID = getModel(
|
|
319
344
|
"vercel-ai-gateway",
|
|
320
345
|
"openai/gpt-5.4-mini"
|
|
321
346
|
).id;
|
|
347
|
+
var DEFAULT_ADVISOR_MODEL_ID = getModel(
|
|
348
|
+
"vercel-ai-gateway",
|
|
349
|
+
"openai/gpt-5.5"
|
|
350
|
+
).id;
|
|
322
351
|
function validateGatewayModelId(raw) {
|
|
323
352
|
const trimmed = toOptionalTrimmed(raw);
|
|
324
353
|
if (trimmed === void 0) return void 0;
|
|
325
354
|
resolveGatewayModel(trimmed);
|
|
326
355
|
return trimmed;
|
|
327
356
|
}
|
|
357
|
+
function readAdvisorConfig(env) {
|
|
358
|
+
return {
|
|
359
|
+
modelId: validateGatewayModelId(env.AI_ADVISOR_MODEL) ?? DEFAULT_ADVISOR_MODEL_ID,
|
|
360
|
+
thinkingLevel: parseAdvisorThinkingLevel(env.AI_ADVISOR_THINKING_LEVEL)
|
|
361
|
+
};
|
|
362
|
+
}
|
|
328
363
|
function readBotConfig(env) {
|
|
329
364
|
const functionMaxDurationSeconds = resolveFunctionMaxDurationSeconds(env);
|
|
330
365
|
const maxTurnTimeoutMs = resolveMaxTurnTimeoutMs(functionMaxDurationSeconds);
|
|
@@ -337,7 +372,8 @@ function readBotConfig(env) {
|
|
|
337
372
|
turnTimeoutMs: parseAgentTurnTimeoutMs(
|
|
338
373
|
env.AGENT_TURN_TIMEOUT_MS,
|
|
339
374
|
maxTurnTimeoutMs
|
|
340
|
-
)
|
|
375
|
+
),
|
|
376
|
+
advisor: readAdvisorConfig(env)
|
|
341
377
|
};
|
|
342
378
|
}
|
|
343
379
|
function readChatConfig(env = process.env) {
|
|
@@ -971,6 +971,9 @@ function setLogContext(context) {
|
|
|
971
971
|
);
|
|
972
972
|
contextStorage.enterWith(merged);
|
|
973
973
|
}
|
|
974
|
+
function getLogContextAttributes() {
|
|
975
|
+
return contextStorage.getStore() ?? {};
|
|
976
|
+
}
|
|
974
977
|
function createLogContextFromRequest(request, context = {}) {
|
|
975
978
|
const url = new URL(request.url);
|
|
976
979
|
return {
|
|
@@ -1052,20 +1055,20 @@ async function withSpan(name, op, context, callback, attributes = {}) {
|
|
|
1052
1055
|
normalizedAttributes[key] = normalizedValue;
|
|
1053
1056
|
}
|
|
1054
1057
|
}
|
|
1055
|
-
return withLogContext(
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
+
return withLogContext(context, () => {
|
|
1059
|
+
const inheritedAttributes = getLogContextAttributes();
|
|
1060
|
+
return sentry_exports.startSpan(
|
|
1058
1061
|
{
|
|
1059
1062
|
name,
|
|
1060
1063
|
op,
|
|
1061
1064
|
attributes: {
|
|
1062
|
-
...
|
|
1065
|
+
...inheritedAttributes,
|
|
1063
1066
|
...normalizedAttributes
|
|
1064
1067
|
}
|
|
1065
1068
|
},
|
|
1066
1069
|
callback
|
|
1067
|
-
)
|
|
1068
|
-
);
|
|
1070
|
+
);
|
|
1071
|
+
});
|
|
1069
1072
|
}
|
|
1070
1073
|
function setSpanAttributes(attributes) {
|
|
1071
1074
|
const sentry = sentry_exports;
|
|
@@ -1246,6 +1249,7 @@ var SHORT_CONFIG_KEY_RE = /^[a-z0-9]+(\.[a-z0-9-]+)*$/;
|
|
|
1246
1249
|
var TARGET_FLAG_RE = /^-{1,2}[A-Za-z0-9][A-Za-z0-9-]*$/;
|
|
1247
1250
|
var AUTH_TOKEN_ENV_RE = /^[A-Z][A-Z0-9_]*$/;
|
|
1248
1251
|
var ENV_VAR_NAME_RE = /^[A-Z_][A-Z0-9_]*$/;
|
|
1252
|
+
var ENV_PLACEHOLDER_RE = /\$\{([A-Z_][A-Z0-9_]*)\}/g;
|
|
1249
1253
|
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])?$/;
|
|
1250
1254
|
var RUNTIME_POSTINSTALL_CMD_RE = /^[A-Za-z0-9._/-]+$/;
|
|
1251
1255
|
var RESERVED_AUTHORIZE_PARAM_KEYS = /* @__PURE__ */ new Set([
|
|
@@ -1340,7 +1344,7 @@ var stringMapSchema = z.record(z.string(), z.unknown()).transform((record, ctx)
|
|
|
1340
1344
|
seen.add(normalizedKey);
|
|
1341
1345
|
result[key] = rawValue.trim();
|
|
1342
1346
|
}
|
|
1343
|
-
return
|
|
1347
|
+
return result;
|
|
1344
1348
|
});
|
|
1345
1349
|
var apiDomainsSchema = z.array(z.unknown()).min(1, {
|
|
1346
1350
|
error: "must be a non-empty array of strings"
|
|
@@ -1433,6 +1437,8 @@ var manifestSourceSchema = z.object({
|
|
|
1433
1437
|
"config-keys": z.array(z.string(), {
|
|
1434
1438
|
error: "must be an array when provided"
|
|
1435
1439
|
}).optional(),
|
|
1440
|
+
"api-domains": apiDomainsSchema.optional(),
|
|
1441
|
+
"api-headers": stringMapSchema.optional(),
|
|
1436
1442
|
credentials: z.record(z.string(), z.unknown(), {
|
|
1437
1443
|
error: "must be an object when provided"
|
|
1438
1444
|
}).optional(),
|
|
@@ -1470,7 +1476,11 @@ function normalizeStringMap(value, prefix, options = {}) {
|
|
|
1470
1476
|
if (!value) {
|
|
1471
1477
|
return void 0;
|
|
1472
1478
|
}
|
|
1473
|
-
|
|
1479
|
+
const keys = Object.keys(value);
|
|
1480
|
+
if (keys.length === 0) {
|
|
1481
|
+
return void 0;
|
|
1482
|
+
}
|
|
1483
|
+
for (const key of keys) {
|
|
1474
1484
|
const normalizedKey = key.toLowerCase();
|
|
1475
1485
|
if (options.reservedKeys?.has(normalizedKey)) {
|
|
1476
1486
|
throw new Error(`${prefix}.${key} is reserved by the runtime`);
|
|
@@ -1481,6 +1491,31 @@ function normalizeStringMap(value, prefix, options = {}) {
|
|
|
1481
1491
|
}
|
|
1482
1492
|
return value;
|
|
1483
1493
|
}
|
|
1494
|
+
function assertDeclaredEnvReferences(value, envVars, context) {
|
|
1495
|
+
for (const match of value.matchAll(ENV_PLACEHOLDER_RE)) {
|
|
1496
|
+
const name = match[1];
|
|
1497
|
+
if (!Object.prototype.hasOwnProperty.call(envVars, name)) {
|
|
1498
|
+
throw new Error(
|
|
1499
|
+
`${context} references env var ${name} which is not declared in env-vars`
|
|
1500
|
+
);
|
|
1501
|
+
}
|
|
1502
|
+
if (envVars[name]?.default !== void 0) {
|
|
1503
|
+
throw new Error(
|
|
1504
|
+
`${context} references env var ${name}, but API header env vars must not declare defaults`
|
|
1505
|
+
);
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
}
|
|
1509
|
+
function normalizeRequiredApiHeaders(value, prefix, envVars) {
|
|
1510
|
+
const apiHeaders = normalizeStringMap(value, prefix);
|
|
1511
|
+
if (!apiHeaders) {
|
|
1512
|
+
throw new Error(`${prefix} must contain at least one header`);
|
|
1513
|
+
}
|
|
1514
|
+
for (const [key, headerValue] of Object.entries(apiHeaders)) {
|
|
1515
|
+
assertDeclaredEnvReferences(headerValue, envVars, `${prefix}.${key}`);
|
|
1516
|
+
}
|
|
1517
|
+
return apiHeaders;
|
|
1518
|
+
}
|
|
1484
1519
|
function normalizeCredentials(data, name) {
|
|
1485
1520
|
const schema = data.type === "oauth-bearer" ? oauthBearerCredentialsSchema : data.type === "github-app" ? githubAppCredentialsSchema : void 0;
|
|
1486
1521
|
if (!schema) {
|
|
@@ -1493,30 +1528,28 @@ function normalizeCredentials(data, name) {
|
|
|
1493
1528
|
throw new Error(issueMessage(result.error, `Plugin ${name} credentials`));
|
|
1494
1529
|
}
|
|
1495
1530
|
if (result.data.type === "oauth-bearer") {
|
|
1531
|
+
const apiHeaders2 = result.data["api-headers"] ? normalizeStringMap(
|
|
1532
|
+
result.data["api-headers"],
|
|
1533
|
+
`Plugin ${name} credentials.api-headers`,
|
|
1534
|
+
{ forbiddenKeys: FORBIDDEN_API_HEADER_NAMES }
|
|
1535
|
+
) : void 0;
|
|
1496
1536
|
return {
|
|
1497
1537
|
type: "oauth-bearer",
|
|
1498
1538
|
apiDomains: result.data["api-domains"],
|
|
1499
|
-
...
|
|
1500
|
-
apiHeaders: normalizeStringMap(
|
|
1501
|
-
result.data["api-headers"],
|
|
1502
|
-
`Plugin ${name} credentials.api-headers`,
|
|
1503
|
-
{ forbiddenKeys: FORBIDDEN_API_HEADER_NAMES }
|
|
1504
|
-
)
|
|
1505
|
-
} : {},
|
|
1539
|
+
...apiHeaders2 ? { apiHeaders: apiHeaders2 } : {},
|
|
1506
1540
|
authTokenEnv: result.data["auth-token-env"],
|
|
1507
1541
|
...result.data["auth-token-placeholder"] ? { authTokenPlaceholder: result.data["auth-token-placeholder"] } : {}
|
|
1508
1542
|
};
|
|
1509
1543
|
}
|
|
1544
|
+
const apiHeaders = result.data["api-headers"] ? normalizeStringMap(
|
|
1545
|
+
result.data["api-headers"],
|
|
1546
|
+
`Plugin ${name} credentials.api-headers`,
|
|
1547
|
+
{ forbiddenKeys: FORBIDDEN_API_HEADER_NAMES }
|
|
1548
|
+
) : void 0;
|
|
1510
1549
|
return {
|
|
1511
1550
|
type: "github-app",
|
|
1512
1551
|
apiDomains: result.data["api-domains"],
|
|
1513
|
-
...
|
|
1514
|
-
apiHeaders: normalizeStringMap(
|
|
1515
|
-
result.data["api-headers"],
|
|
1516
|
-
`Plugin ${name} credentials.api-headers`,
|
|
1517
|
-
{ forbiddenKeys: FORBIDDEN_API_HEADER_NAMES }
|
|
1518
|
-
)
|
|
1519
|
-
} : {},
|
|
1552
|
+
...apiHeaders ? { apiHeaders } : {},
|
|
1520
1553
|
authTokenEnv: result.data["auth-token-env"],
|
|
1521
1554
|
...result.data["auth-token-placeholder"] ? { authTokenPlaceholder: result.data["auth-token-placeholder"] } : {},
|
|
1522
1555
|
appIdEnv: result.data["app-id-env"],
|
|
@@ -1650,7 +1683,6 @@ function normalizeRuntimePostinstall(commands, name) {
|
|
|
1650
1683
|
}
|
|
1651
1684
|
return parsed.length > 0 ? parsed : void 0;
|
|
1652
1685
|
}
|
|
1653
|
-
var ENV_PLACEHOLDER_RE = /\$\{([A-Z_][A-Z0-9_]*)\}/g;
|
|
1654
1686
|
var envVarDeclarationSchema = z.preprocess(
|
|
1655
1687
|
(value) => value === null || value === void 0 ? {} : value,
|
|
1656
1688
|
z.object({
|
|
@@ -1714,16 +1746,13 @@ function normalizeMcp(data, envVars, name) {
|
|
|
1714
1746
|
if (!result.success) {
|
|
1715
1747
|
throw new Error(issueMessage(result.error, `Plugin ${name} mcp`));
|
|
1716
1748
|
}
|
|
1749
|
+
const headers = result.data.headers ? normalizeStringMap(result.data.headers, `Plugin ${name} mcp.headers`, {
|
|
1750
|
+
forbiddenKeys: FORBIDDEN_API_HEADER_NAMES
|
|
1751
|
+
}) : void 0;
|
|
1717
1752
|
return {
|
|
1718
1753
|
transport: "http",
|
|
1719
1754
|
url: result.data.url,
|
|
1720
|
-
...
|
|
1721
|
-
headers: normalizeStringMap(
|
|
1722
|
-
result.data.headers,
|
|
1723
|
-
`Plugin ${name} mcp.headers`,
|
|
1724
|
-
{ forbiddenKeys: FORBIDDEN_API_HEADER_NAMES }
|
|
1725
|
-
)
|
|
1726
|
-
} : {},
|
|
1755
|
+
...headers ? { headers } : {},
|
|
1727
1756
|
...result.data["allowed-tools"] ? { allowedTools: result.data["allowed-tools"] } : {}
|
|
1728
1757
|
};
|
|
1729
1758
|
}
|
|
@@ -1761,6 +1790,16 @@ function parsePluginManifest(raw, dir) {
|
|
|
1761
1790
|
`Plugin ${parsedYaml.name ?? "unknown"} config-keys must be an array when provided`
|
|
1762
1791
|
);
|
|
1763
1792
|
}
|
|
1793
|
+
if (path3 === "api-domains") {
|
|
1794
|
+
throw new Error(
|
|
1795
|
+
`Plugin ${parsedYaml.name ?? "unknown"} api-domains must be a non-empty array of domains`
|
|
1796
|
+
);
|
|
1797
|
+
}
|
|
1798
|
+
if (path3 === "api-headers") {
|
|
1799
|
+
throw new Error(
|
|
1800
|
+
`Plugin ${parsedYaml.name ?? "unknown"} api-headers must be an object when provided`
|
|
1801
|
+
);
|
|
1802
|
+
}
|
|
1764
1803
|
if (path3 === "credentials") {
|
|
1765
1804
|
throw new Error(
|
|
1766
1805
|
`Plugin ${parsedYaml.name ?? "unknown"} credentials must be an object when provided`
|
|
@@ -1813,16 +1852,29 @@ function parsePluginManifest(raw, dir) {
|
|
|
1813
1852
|
}
|
|
1814
1853
|
return `${data.name}.${key}`;
|
|
1815
1854
|
});
|
|
1855
|
+
const envVars = data["env-vars"] ? normalizeEnvVars(data["env-vars"], data.name) : {};
|
|
1856
|
+
const apiHeaders = data["api-headers"] ? normalizeRequiredApiHeaders(
|
|
1857
|
+
data["api-headers"],
|
|
1858
|
+
`Plugin ${data.name} api-headers`,
|
|
1859
|
+
envVars
|
|
1860
|
+
) : void 0;
|
|
1861
|
+
if (apiHeaders && !data["api-domains"]) {
|
|
1862
|
+
throw new Error(`Plugin ${data.name} api-headers requires api-domains`);
|
|
1863
|
+
}
|
|
1864
|
+
if (data["api-domains"] && !apiHeaders) {
|
|
1865
|
+
throw new Error(`Plugin ${data.name} api-domains requires api-headers`);
|
|
1866
|
+
}
|
|
1816
1867
|
const credentials = data.credentials ? normalizeCredentials(data.credentials, data.name) : void 0;
|
|
1817
1868
|
const runtimeDependencies = data["runtime-dependencies"] ? normalizeRuntimeDependencies(data["runtime-dependencies"], data.name) : void 0;
|
|
1818
1869
|
const runtimePostinstall = data["runtime-postinstall"] ? normalizeRuntimePostinstall(data["runtime-postinstall"], data.name) : void 0;
|
|
1819
|
-
const envVars = data["env-vars"] ? normalizeEnvVars(data["env-vars"], data.name) : {};
|
|
1820
1870
|
const mcp = data.mcp ? normalizeMcp(data.mcp, envVars, data.name) : void 0;
|
|
1821
1871
|
const manifest = {
|
|
1822
1872
|
name: data.name,
|
|
1823
1873
|
description: data.description,
|
|
1824
1874
|
capabilities,
|
|
1825
1875
|
configKeys,
|
|
1876
|
+
...data["api-domains"] ? { apiDomains: data["api-domains"] } : {},
|
|
1877
|
+
...apiHeaders ? { apiHeaders } : {},
|
|
1826
1878
|
...Object.keys(envVars).length > 0 ? { envVars } : {},
|
|
1827
1879
|
...credentials ? { credentials } : {},
|
|
1828
1880
|
...runtimeDependencies ? { runtimeDependencies } : {},
|
|
@@ -1903,7 +1955,76 @@ import { readFileSync, readdirSync, statSync } from "fs";
|
|
|
1903
1955
|
import path2 from "path";
|
|
1904
1956
|
|
|
1905
1957
|
// src/chat/plugins/auth/github-app-broker.ts
|
|
1906
|
-
import { createPrivateKey, createSign, randomUUID } from "crypto";
|
|
1958
|
+
import { createPrivateKey, createSign, randomUUID as randomUUID2 } from "crypto";
|
|
1959
|
+
|
|
1960
|
+
// src/chat/credentials/header-transforms.ts
|
|
1961
|
+
function mergeHeaderTransforms(transforms) {
|
|
1962
|
+
const byDomain = /* @__PURE__ */ new Map();
|
|
1963
|
+
for (const transform of transforms) {
|
|
1964
|
+
byDomain.set(transform.domain, {
|
|
1965
|
+
...byDomain.get(transform.domain) ?? {},
|
|
1966
|
+
...transform.headers
|
|
1967
|
+
});
|
|
1968
|
+
}
|
|
1969
|
+
return [...byDomain.entries()].map(([domain, headers]) => ({
|
|
1970
|
+
domain,
|
|
1971
|
+
headers
|
|
1972
|
+
}));
|
|
1973
|
+
}
|
|
1974
|
+
|
|
1975
|
+
// src/chat/plugins/auth/api-headers-broker.ts
|
|
1976
|
+
import { randomUUID } from "crypto";
|
|
1977
|
+
var MAX_LEASE_MS = 60 * 60 * 1e3;
|
|
1978
|
+
var ENV_PLACEHOLDER_RE2 = /\$\{([A-Z_][A-Z0-9_]*)\}/g;
|
|
1979
|
+
function resolveHeaders(provider, headers) {
|
|
1980
|
+
return Object.fromEntries(
|
|
1981
|
+
Object.entries(headers).map(([key, value]) => {
|
|
1982
|
+
const resolved = value.replace(ENV_PLACEHOLDER_RE2, (_match, name) => {
|
|
1983
|
+
const envName = name;
|
|
1984
|
+
const envValue = process.env[envName]?.trim();
|
|
1985
|
+
if (!envValue) {
|
|
1986
|
+
throw new Error(
|
|
1987
|
+
`Missing ${envName} for API header provider "${provider}"`
|
|
1988
|
+
);
|
|
1989
|
+
}
|
|
1990
|
+
return envValue;
|
|
1991
|
+
});
|
|
1992
|
+
return [key, resolved];
|
|
1993
|
+
})
|
|
1994
|
+
);
|
|
1995
|
+
}
|
|
1996
|
+
function resolveApiHeaderTransforms(manifest) {
|
|
1997
|
+
const { apiDomains, apiHeaders } = manifest;
|
|
1998
|
+
if (!apiDomains || !apiHeaders) {
|
|
1999
|
+
return [];
|
|
2000
|
+
}
|
|
2001
|
+
const resolvedHeaders = resolveHeaders(manifest.name, apiHeaders);
|
|
2002
|
+
return apiDomains.map((domain) => ({
|
|
2003
|
+
domain,
|
|
2004
|
+
headers: resolvedHeaders
|
|
2005
|
+
}));
|
|
2006
|
+
}
|
|
2007
|
+
function createApiHeadersBroker(manifest) {
|
|
2008
|
+
const provider = manifest.name;
|
|
2009
|
+
return {
|
|
2010
|
+
async issue(input) {
|
|
2011
|
+
const headerTransforms = resolveApiHeaderTransforms(manifest);
|
|
2012
|
+
if (headerTransforms.length === 0) {
|
|
2013
|
+
throw new Error(`No API headers configured for plugin "${provider}"`);
|
|
2014
|
+
}
|
|
2015
|
+
return {
|
|
2016
|
+
id: randomUUID(),
|
|
2017
|
+
provider,
|
|
2018
|
+
env: {},
|
|
2019
|
+
headerTransforms,
|
|
2020
|
+
expiresAt: new Date(Date.now() + MAX_LEASE_MS).toISOString(),
|
|
2021
|
+
metadata: {
|
|
2022
|
+
reason: input.reason
|
|
2023
|
+
}
|
|
2024
|
+
};
|
|
2025
|
+
}
|
|
2026
|
+
};
|
|
2027
|
+
}
|
|
1907
2028
|
|
|
1908
2029
|
// src/chat/plugins/auth/auth-token-placeholder.ts
|
|
1909
2030
|
var DEFAULT_PLACEHOLDERS = {
|
|
@@ -1915,7 +2036,7 @@ function resolveAuthTokenPlaceholder(credentials) {
|
|
|
1915
2036
|
}
|
|
1916
2037
|
|
|
1917
2038
|
// src/chat/plugins/auth/github-app-broker.ts
|
|
1918
|
-
var
|
|
2039
|
+
var MAX_LEASE_MS2 = 60 * 60 * 1e3;
|
|
1919
2040
|
function base64Url(input) {
|
|
1920
2041
|
return Buffer.from(input).toString("base64").replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
1921
2042
|
}
|
|
@@ -2060,6 +2181,7 @@ function createGitHubAppBroker(manifest, credentials) {
|
|
|
2060
2181
|
} = credentials;
|
|
2061
2182
|
const apiBase = `https://${apiDomains[0]}`;
|
|
2062
2183
|
const placeholder = resolveAuthTokenPlaceholder(credentials);
|
|
2184
|
+
const pluginHeaderTransforms = () => resolveApiHeaderTransforms(manifest);
|
|
2063
2185
|
const GIT_DOMAIN = "github.com";
|
|
2064
2186
|
const GIT_CAPABILITIES = /* @__PURE__ */ new Set([
|
|
2065
2187
|
`${provider}.contents.read`,
|
|
@@ -2097,16 +2219,19 @@ function createGitHubAppBroker(manifest, credentials) {
|
|
|
2097
2219
|
const now = Date.now();
|
|
2098
2220
|
if (cached && cached.expiresAt - now > 2 * 60 * 1e3) {
|
|
2099
2221
|
return {
|
|
2100
|
-
id:
|
|
2222
|
+
id: randomUUID2(),
|
|
2101
2223
|
provider,
|
|
2102
2224
|
env: { [authTokenEnv]: placeholder },
|
|
2103
|
-
headerTransforms:
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2225
|
+
headerTransforms: mergeHeaderTransforms([
|
|
2226
|
+
...pluginHeaderTransforms(),
|
|
2227
|
+
...leaseDomains.map((domain) => ({
|
|
2228
|
+
domain,
|
|
2229
|
+
headers: {
|
|
2230
|
+
...apiHeaders ?? {},
|
|
2231
|
+
Authorization: authorizationFor(domain, cached.token)
|
|
2232
|
+
}
|
|
2233
|
+
}))
|
|
2234
|
+
]),
|
|
2110
2235
|
expiresAt: new Date(cached.expiresAt).toISOString(),
|
|
2111
2236
|
metadata: {
|
|
2112
2237
|
installationId: String(cached.installationId),
|
|
@@ -2130,7 +2255,7 @@ function createGitHubAppBroker(manifest, credentials) {
|
|
|
2130
2255
|
const providerExpiresAtMs = Date.parse(accessTokenResponse.expires_at);
|
|
2131
2256
|
const expiresAtMs = Math.min(
|
|
2132
2257
|
providerExpiresAtMs,
|
|
2133
|
-
Date.now() +
|
|
2258
|
+
Date.now() + MAX_LEASE_MS2
|
|
2134
2259
|
);
|
|
2135
2260
|
tokenCache.set(cacheKey, {
|
|
2136
2261
|
installationId,
|
|
@@ -2138,16 +2263,22 @@ function createGitHubAppBroker(manifest, credentials) {
|
|
|
2138
2263
|
expiresAt: expiresAtMs
|
|
2139
2264
|
});
|
|
2140
2265
|
return {
|
|
2141
|
-
id:
|
|
2266
|
+
id: randomUUID2(),
|
|
2142
2267
|
provider,
|
|
2143
2268
|
env: { [authTokenEnv]: placeholder },
|
|
2144
|
-
headerTransforms:
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2269
|
+
headerTransforms: mergeHeaderTransforms([
|
|
2270
|
+
...pluginHeaderTransforms(),
|
|
2271
|
+
...leaseDomains.map((domain) => ({
|
|
2272
|
+
domain,
|
|
2273
|
+
headers: {
|
|
2274
|
+
...apiHeaders ?? {},
|
|
2275
|
+
Authorization: authorizationFor(
|
|
2276
|
+
domain,
|
|
2277
|
+
accessTokenResponse.token
|
|
2278
|
+
)
|
|
2279
|
+
}
|
|
2280
|
+
}))
|
|
2281
|
+
]),
|
|
2151
2282
|
expiresAt: new Date(expiresAtMs).toISOString(),
|
|
2152
2283
|
metadata: {
|
|
2153
2284
|
installationId: String(installationId),
|
|
@@ -2159,7 +2290,7 @@ function createGitHubAppBroker(manifest, credentials) {
|
|
|
2159
2290
|
}
|
|
2160
2291
|
|
|
2161
2292
|
// src/chat/plugins/auth/oauth-bearer-broker.ts
|
|
2162
|
-
import { randomUUID as
|
|
2293
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
2163
2294
|
|
|
2164
2295
|
// src/chat/credentials/broker.ts
|
|
2165
2296
|
var CredentialUnavailableError = class extends Error {
|
|
@@ -2270,7 +2401,7 @@ function parseOAuthTokenResponse(data, fallbackScope) {
|
|
|
2270
2401
|
}
|
|
2271
2402
|
|
|
2272
2403
|
// src/chat/plugins/auth/oauth-bearer-broker.ts
|
|
2273
|
-
var
|
|
2404
|
+
var MAX_LEASE_MS3 = 60 * 60 * 1e3;
|
|
2274
2405
|
var REFRESH_BUFFER_MS = 5 * 60 * 1e3;
|
|
2275
2406
|
async function refreshAccessToken(refreshToken, oauth, fallbackScope) {
|
|
2276
2407
|
const clientId = process.env[oauth.clientIdEnv]?.trim();
|
|
@@ -2302,21 +2433,25 @@ async function refreshAccessToken(refreshToken, oauth, fallbackScope) {
|
|
|
2302
2433
|
return parseOAuthTokenResponse(data, fallbackScope);
|
|
2303
2434
|
}
|
|
2304
2435
|
function getLeaseExpiry(expiresAt) {
|
|
2305
|
-
return expiresAt ? Math.min(expiresAt, Date.now() +
|
|
2436
|
+
return expiresAt ? Math.min(expiresAt, Date.now() + MAX_LEASE_MS3) : Date.now() + MAX_LEASE_MS3;
|
|
2306
2437
|
}
|
|
2307
2438
|
function createOAuthBearerBroker(manifest, credentials, deps) {
|
|
2308
2439
|
const provider = manifest.name;
|
|
2309
2440
|
const { apiDomains, apiHeaders, authTokenEnv } = credentials;
|
|
2310
2441
|
const authTokenPlaceholder = resolveAuthTokenPlaceholder(credentials);
|
|
2442
|
+
const pluginHeaderTransforms = () => resolveApiHeaderTransforms(manifest);
|
|
2311
2443
|
function buildLease(token, expiresAtMs, reason) {
|
|
2312
2444
|
return {
|
|
2313
|
-
id:
|
|
2445
|
+
id: randomUUID3(),
|
|
2314
2446
|
provider,
|
|
2315
2447
|
env: { [authTokenEnv]: authTokenPlaceholder },
|
|
2316
|
-
headerTransforms:
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2448
|
+
headerTransforms: mergeHeaderTransforms([
|
|
2449
|
+
...pluginHeaderTransforms(),
|
|
2450
|
+
...apiDomains.map((domain) => ({
|
|
2451
|
+
domain,
|
|
2452
|
+
headers: { ...apiHeaders ?? {}, Authorization: `Bearer ${token}` }
|
|
2453
|
+
}))
|
|
2454
|
+
]),
|
|
2320
2455
|
expiresAt: new Date(expiresAtMs).toISOString(),
|
|
2321
2456
|
metadata: { reason }
|
|
2322
2457
|
};
|
|
@@ -2327,7 +2462,7 @@ function createOAuthBearerBroker(manifest, credentials, deps) {
|
|
|
2327
2462
|
const oauth = manifest.oauth;
|
|
2328
2463
|
if (!oauth) {
|
|
2329
2464
|
if (envToken) {
|
|
2330
|
-
return buildLease(envToken, Date.now() +
|
|
2465
|
+
return buildLease(envToken, Date.now() + MAX_LEASE_MS3, input.reason);
|
|
2331
2466
|
}
|
|
2332
2467
|
throw new CredentialUnavailableError(
|
|
2333
2468
|
provider,
|
|
@@ -2734,11 +2869,15 @@ function createPluginBroker(provider, deps) {
|
|
|
2734
2869
|
throw new Error(`Unknown plugin provider: "${provider}"`);
|
|
2735
2870
|
}
|
|
2736
2871
|
const { credentials, name } = plugin.manifest;
|
|
2737
|
-
if (!credentials) {
|
|
2738
|
-
throw new Error(
|
|
2872
|
+
if (!credentials && !plugin.manifest.apiHeaders) {
|
|
2873
|
+
throw new Error(
|
|
2874
|
+
`Provider "${name}" has no credentials or API headers configured`
|
|
2875
|
+
);
|
|
2739
2876
|
}
|
|
2740
2877
|
let broker;
|
|
2741
|
-
if (credentials
|
|
2878
|
+
if (!credentials) {
|
|
2879
|
+
broker = createApiHeadersBroker(plugin.manifest);
|
|
2880
|
+
} else if (credentials.type === "oauth-bearer") {
|
|
2742
2881
|
broker = createOAuthBearerBroker(plugin.manifest, credentials, deps);
|
|
2743
2882
|
} else if (credentials.type === "github-app") {
|
|
2744
2883
|
broker = createGitHubAppBroker(plugin.manifest, credentials);
|
|
@@ -2773,6 +2912,7 @@ export {
|
|
|
2773
2912
|
serializeGenAiAttribute,
|
|
2774
2913
|
extractGenAiUsageSummary,
|
|
2775
2914
|
extractGenAiUsageAttributes,
|
|
2915
|
+
mergeHeaderTransforms,
|
|
2776
2916
|
resolveAuthTokenPlaceholder,
|
|
2777
2917
|
parsePluginManifest,
|
|
2778
2918
|
CredentialUnavailableError,
|
package/dist/cli/check.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
parseSkillFile
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-LAD5O3RX.js";
|
|
4
4
|
import {
|
|
5
5
|
parsePluginManifest
|
|
6
|
-
} from "../chunk-
|
|
6
|
+
} from "../chunk-QZRPUFO6.js";
|
|
7
7
|
import "../chunk-Z3YD6NHK.js";
|
|
8
8
|
import "../chunk-XPXD3FCE.js";
|
|
9
9
|
import "../chunk-2KG3PWR4.js";
|