@sentry/junior 0.33.0 → 0.34.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 +128 -102
- package/dist/{chunk-3M7ZD6FF.js → chunk-HZIJ4BSE.js} +60 -55
- 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 +1 -1
package/dist/app.js
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
findSkillByName,
|
|
4
4
|
loadSkillsByName,
|
|
5
5
|
parseSkillInvocation
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-LAD5O3RX.js";
|
|
7
7
|
import {
|
|
8
8
|
GEN_AI_PROVIDER_NAME,
|
|
9
9
|
MISSING_GATEWAY_CREDENTIALS_ERROR,
|
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
runNonInteractiveCommand,
|
|
31
31
|
sandboxSkillDir,
|
|
32
32
|
sandboxSkillFile
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-HZIJ4BSE.js";
|
|
34
34
|
import {
|
|
35
35
|
CredentialUnavailableError,
|
|
36
36
|
buildOAuthTokenRequest,
|
|
@@ -53,6 +53,7 @@ import {
|
|
|
53
53
|
logException,
|
|
54
54
|
logInfo,
|
|
55
55
|
logWarn,
|
|
56
|
+
mergeHeaderTransforms,
|
|
56
57
|
parseOAuthTokenResponse,
|
|
57
58
|
resolveAuthTokenPlaceholder,
|
|
58
59
|
resolveErrorReference,
|
|
@@ -64,7 +65,7 @@ import {
|
|
|
64
65
|
toOptionalString,
|
|
65
66
|
withContext,
|
|
66
67
|
withSpan
|
|
67
|
-
} from "./chunk-
|
|
68
|
+
} from "./chunk-QZRPUFO6.js";
|
|
68
69
|
import "./chunk-Z3YD6NHK.js";
|
|
69
70
|
import {
|
|
70
71
|
discoverInstalledPluginPackageContent,
|
|
@@ -3137,7 +3138,7 @@ function buildOutputSection() {
|
|
|
3137
3138
|
return [
|
|
3138
3139
|
openTag,
|
|
3139
3140
|
"- Start with the answer or result, not internal process narration.",
|
|
3140
|
-
"- Use Slack-flavored Markdown: **bold** section labels, `code`, [text](url) links, bullet lists, and fenced code blocks. No tables.",
|
|
3141
|
+
"- Use Slack-flavored Markdown: **bold** section labels, `code`, [text](url) links, bullet lists, and fenced code blocks. No tables. When the answer primarily lists several URLs, show each URL bare instead of as a labeled link.",
|
|
3141
3142
|
"- Keep replies brief and scannable; use bullets or short code blocks when helpful, and one compact thread reply when it fits.",
|
|
3142
3143
|
"- When a research or document-style answer would benefit from continuation, multiple sections, or future reference value, create a Slack canvas and keep the thread reply to one or two short sentences plus the link; do not recap the canvas contents.",
|
|
3143
3144
|
"- Unless a successful Slack side-effect tool intentionally satisfied the request by itself, end every turn with a final user-facing markdown response.",
|
|
@@ -3366,7 +3367,7 @@ var SkillCapabilityRuntime = class {
|
|
|
3366
3367
|
throw new Error("Credential enablement requires requester context");
|
|
3367
3368
|
}
|
|
3368
3369
|
const plugin = getPluginDefinition(provider);
|
|
3369
|
-
if (!plugin?.manifest.credentials) {
|
|
3370
|
+
if (!plugin?.manifest.credentials && !plugin?.manifest.apiHeaders) {
|
|
3370
3371
|
return void 0;
|
|
3371
3372
|
}
|
|
3372
3373
|
const existing = this.enabledByProvider.get(provider);
|
|
@@ -3498,19 +3499,22 @@ var TestCredentialBroker = class {
|
|
|
3498
3499
|
async issue(input) {
|
|
3499
3500
|
const token = process.env.EVAL_TEST_CREDENTIAL_TOKEN?.trim() || "eval-test-token";
|
|
3500
3501
|
const expiresAt = new Date(Date.now() + 5 * 60 * 1e3).toISOString();
|
|
3502
|
+
const env = this.config.envKey && this.config.placeholder ? { [this.config.envKey]: this.config.placeholder } : {};
|
|
3503
|
+
const tokenTransforms = this.config.domains?.map((domain) => ({
|
|
3504
|
+
domain,
|
|
3505
|
+
headers: {
|
|
3506
|
+
...this.config.apiHeaders ?? {},
|
|
3507
|
+
Authorization: `Bearer ${token}`
|
|
3508
|
+
}
|
|
3509
|
+
})) ?? [];
|
|
3501
3510
|
return {
|
|
3502
3511
|
id: randomUUID2(),
|
|
3503
3512
|
provider: this.config.provider,
|
|
3504
|
-
env
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
headers: {
|
|
3510
|
-
...this.config.apiHeaders ?? {},
|
|
3511
|
-
Authorization: `Bearer ${token}`
|
|
3512
|
-
}
|
|
3513
|
-
})),
|
|
3513
|
+
env,
|
|
3514
|
+
headerTransforms: mergeHeaderTransforms([
|
|
3515
|
+
...this.config.headerTransforms?.() ?? [],
|
|
3516
|
+
...tokenTransforms
|
|
3517
|
+
]),
|
|
3514
3518
|
expiresAt,
|
|
3515
3519
|
metadata: {
|
|
3516
3520
|
reason: input.reason
|
|
@@ -3520,24 +3524,50 @@ var TestCredentialBroker = class {
|
|
|
3520
3524
|
};
|
|
3521
3525
|
|
|
3522
3526
|
// src/chat/capabilities/factory.ts
|
|
3527
|
+
var ENV_PLACEHOLDER_RE = /\$\{([A-Z_][A-Z0-9_]*)\}/g;
|
|
3523
3528
|
function createUserTokenStore() {
|
|
3524
3529
|
return new StateAdapterTokenStore(getStateAdapter());
|
|
3525
3530
|
}
|
|
3531
|
+
function resolveTestApiHeaderTransforms(manifest) {
|
|
3532
|
+
const { apiDomains, apiHeaders } = manifest;
|
|
3533
|
+
if (!apiDomains || !apiHeaders) {
|
|
3534
|
+
return [];
|
|
3535
|
+
}
|
|
3536
|
+
const headers = Object.fromEntries(
|
|
3537
|
+
Object.entries(apiHeaders).map(([key, value]) => [
|
|
3538
|
+
key,
|
|
3539
|
+
value.replace(ENV_PLACEHOLDER_RE, (_match, name) => {
|
|
3540
|
+
return `eval-test-${String(name).toLowerCase().replaceAll("_", "-")}`;
|
|
3541
|
+
})
|
|
3542
|
+
])
|
|
3543
|
+
);
|
|
3544
|
+
return apiDomains.map((domain) => ({ domain, headers }));
|
|
3545
|
+
}
|
|
3526
3546
|
function createSkillCapabilityRuntime(options = {}) {
|
|
3527
3547
|
logCapabilityCatalogLoadedOnce();
|
|
3528
3548
|
const useTestBroker = process.env.EVAL_ENABLE_TEST_CREDENTIALS === "1";
|
|
3529
3549
|
const userTokenStore = createUserTokenStore();
|
|
3530
3550
|
const brokersByProvider = {};
|
|
3531
3551
|
for (const plugin of getPluginProviders()) {
|
|
3532
|
-
const { credentials, name } = plugin.manifest;
|
|
3552
|
+
const { apiHeaders, credentials, name } = plugin.manifest;
|
|
3553
|
+
if (!credentials && !apiHeaders) {
|
|
3554
|
+
continue;
|
|
3555
|
+
}
|
|
3533
3556
|
if (!credentials) {
|
|
3557
|
+
brokersByProvider[name] = useTestBroker ? new TestCredentialBroker({
|
|
3558
|
+
provider: name,
|
|
3559
|
+
headerTransforms: () => resolveTestApiHeaderTransforms(plugin.manifest)
|
|
3560
|
+
}) : createPluginBroker(name, { userTokenStore });
|
|
3534
3561
|
continue;
|
|
3535
3562
|
}
|
|
3536
3563
|
const placeholder = resolveAuthTokenPlaceholder(credentials);
|
|
3537
3564
|
brokersByProvider[name] = useTestBroker ? new TestCredentialBroker({
|
|
3538
3565
|
provider: name,
|
|
3539
3566
|
domains: credentials.apiDomains,
|
|
3540
|
-
apiHeaders: credentials.apiHeaders,
|
|
3567
|
+
...credentials.apiHeaders ? { apiHeaders: credentials.apiHeaders } : {},
|
|
3568
|
+
...apiHeaders ? {
|
|
3569
|
+
headerTransforms: () => resolveTestApiHeaderTransforms(plugin.manifest)
|
|
3570
|
+
} : {},
|
|
3541
3571
|
envKey: credentials.authTokenEnv,
|
|
3542
3572
|
placeholder
|
|
3543
3573
|
}) : createPluginBroker(name, { userTokenStore });
|
|
@@ -4108,7 +4138,6 @@ var PluginMcpClient = class {
|
|
|
4108
4138
|
setSpanAttributes({
|
|
4109
4139
|
"mcp.method.name": MCP_TOOLS_CALL_METHOD,
|
|
4110
4140
|
"gen_ai.operation.name": "execute_tool",
|
|
4111
|
-
"gen_ai.tool.name": name,
|
|
4112
4141
|
...this.transport?.sessionId ? { "mcp.session.id": this.transport.sessionId } : {},
|
|
4113
4142
|
...this.transport?.protocolVersion ? { "mcp.protocol.version": this.transport.protocolVersion } : {},
|
|
4114
4143
|
...getMcpNetworkAttributes(url)
|
|
@@ -4458,7 +4487,6 @@ var McpToolManager = class {
|
|
|
4458
4487
|
execute: async (args) => {
|
|
4459
4488
|
const resolvedArgs = typeof args === "object" && args !== null ? args : {};
|
|
4460
4489
|
const baseAttributes = {
|
|
4461
|
-
"gen_ai.tool.name": tool2.name,
|
|
4462
4490
|
"mcp.method.name": "tools/call"
|
|
4463
4491
|
};
|
|
4464
4492
|
setSpanAttributes(baseAttributes);
|
|
@@ -8752,12 +8780,6 @@ function createAgentTools(tools, sandbox, spanContext, onStatus, sandboxExecutor
|
|
|
8752
8780
|
execute: async (toolCallId, params) => {
|
|
8753
8781
|
const normalizedToolCallId = typeof toolCallId === "string" && toolCallId.length > 0 ? toolCallId : void 0;
|
|
8754
8782
|
const toolArgumentsAttribute = serializeGenAiAttribute(params);
|
|
8755
|
-
const traceToolContext = {
|
|
8756
|
-
...spanContext,
|
|
8757
|
-
conversationId: spanContext.conversationId,
|
|
8758
|
-
turnId: spanContext.turnId,
|
|
8759
|
-
agentId: spanContext.agentId
|
|
8760
|
-
};
|
|
8761
8783
|
if (toolName === "reportProgress") {
|
|
8762
8784
|
const status = buildReportedProgressStatus(params);
|
|
8763
8785
|
if (status) {
|
|
@@ -8812,9 +8834,8 @@ function createAgentTools(tools, sandbox, spanContext, onStatus, sandboxExecutor
|
|
|
8812
8834
|
details: normalized.details
|
|
8813
8835
|
});
|
|
8814
8836
|
}
|
|
8815
|
-
const
|
|
8816
|
-
|
|
8817
|
-
);
|
|
8837
|
+
const resultAttributeValue = normalized.details && typeof normalized.details === "object" && "rawResult" in normalized.details && normalized.details.rawResult !== void 0 ? normalized.details.rawResult : normalized.details;
|
|
8838
|
+
const toolResultAttribute = serializeGenAiAttribute(resultAttributeValue);
|
|
8818
8839
|
if (toolResultAttribute) {
|
|
8819
8840
|
setSpanAttributes({
|
|
8820
8841
|
"gen_ai.tool.call.result": toolResultAttribute
|
|
@@ -8830,7 +8851,7 @@ function createAgentTools(tools, sandbox, spanContext, onStatus, sandboxExecutor
|
|
|
8830
8851
|
toolName,
|
|
8831
8852
|
normalizedToolCallId,
|
|
8832
8853
|
shouldTrace,
|
|
8833
|
-
|
|
8854
|
+
spanContext
|
|
8834
8855
|
);
|
|
8835
8856
|
}
|
|
8836
8857
|
},
|
|
@@ -9888,13 +9909,17 @@ function commandTargetsProvider(provider, command, details) {
|
|
|
9888
9909
|
}
|
|
9889
9910
|
const plugin = getPluginDefinition(provider);
|
|
9890
9911
|
const candidates = /* @__PURE__ */ new Set([provider.toLowerCase()]);
|
|
9891
|
-
const
|
|
9912
|
+
const manifest = plugin?.manifest;
|
|
9913
|
+
const credentials = manifest?.credentials;
|
|
9892
9914
|
if (credentials) {
|
|
9893
9915
|
candidates.add(credentials.authTokenEnv.toLowerCase());
|
|
9894
9916
|
for (const domain of credentials.apiDomains) {
|
|
9895
9917
|
candidates.add(domain.toLowerCase());
|
|
9896
9918
|
}
|
|
9897
9919
|
}
|
|
9920
|
+
for (const domain of manifest?.apiDomains ?? []) {
|
|
9921
|
+
candidates.add(domain.toLowerCase());
|
|
9922
|
+
}
|
|
9898
9923
|
const combinedText = `${normalizedCommand}
|
|
9899
9924
|
${details.stdout?.toLowerCase() ?? ""}
|
|
9900
9925
|
${details.stderr?.toLowerCase() ?? ""}`;
|
|
@@ -13485,6 +13510,7 @@ function buildFailureMessage(reference) {
|
|
|
13485
13510
|
}
|
|
13486
13511
|
function buildLogContext(deps, args) {
|
|
13487
13512
|
return {
|
|
13513
|
+
conversationId: args.threadId ?? args.runId,
|
|
13488
13514
|
slackThreadId: args.threadId,
|
|
13489
13515
|
slackUserId: args.requesterId,
|
|
13490
13516
|
slackUserName: args.requesterUserName,
|
|
@@ -13609,78 +13635,6 @@ function createSlackTurnRuntime(deps) {
|
|
|
13609
13635
|
const threadId = deps.getThreadId(thread, message);
|
|
13610
13636
|
const channelId = deps.getChannelId(thread, message);
|
|
13611
13637
|
const runId = deps.getRunId(thread, message);
|
|
13612
|
-
const rawUserText = message.text;
|
|
13613
|
-
const userText = deps.stripLeadingBotMention(rawUserText, {
|
|
13614
|
-
stripLeadingSlackMentionToken: Boolean(message.isMention)
|
|
13615
|
-
});
|
|
13616
|
-
const context = {
|
|
13617
|
-
threadId,
|
|
13618
|
-
requesterId: message.author.userId,
|
|
13619
|
-
channelId,
|
|
13620
|
-
runId
|
|
13621
|
-
};
|
|
13622
|
-
const preflightDecision = getSubscribedReplyPreflightDecision({
|
|
13623
|
-
botUserName: deps.assistantUserName,
|
|
13624
|
-
rawText: rawUserText,
|
|
13625
|
-
text: userText,
|
|
13626
|
-
isExplicitMention: Boolean(message.isMention)
|
|
13627
|
-
});
|
|
13628
|
-
if (preflightDecision && !preflightDecision.shouldReply) {
|
|
13629
|
-
const reason = preflightDecision.reasonDetail ? `${preflightDecision.reason}:${preflightDecision.reasonDetail}` : preflightDecision.reason;
|
|
13630
|
-
await skipSubscribedMessage({
|
|
13631
|
-
thread,
|
|
13632
|
-
message,
|
|
13633
|
-
decision: { shouldReply: false, reason },
|
|
13634
|
-
context,
|
|
13635
|
-
userText
|
|
13636
|
-
});
|
|
13637
|
-
return;
|
|
13638
|
-
}
|
|
13639
|
-
const preparedState = await deps.prepareTurnState({
|
|
13640
|
-
thread,
|
|
13641
|
-
message,
|
|
13642
|
-
userText,
|
|
13643
|
-
explicitMention: Boolean(message.isMention),
|
|
13644
|
-
context
|
|
13645
|
-
});
|
|
13646
|
-
await deps.persistPreparedState({
|
|
13647
|
-
thread,
|
|
13648
|
-
preparedState
|
|
13649
|
-
});
|
|
13650
|
-
const decision = await deps.decideSubscribedReply({
|
|
13651
|
-
rawText: rawUserText,
|
|
13652
|
-
text: userText,
|
|
13653
|
-
conversationContext: deps.getPreparedConversationContext(preparedState),
|
|
13654
|
-
hasAttachments: message.attachments.length > 0,
|
|
13655
|
-
isExplicitMention: Boolean(message.isMention),
|
|
13656
|
-
context
|
|
13657
|
-
});
|
|
13658
|
-
if (await maybeHandleThreadOptOutDecision({
|
|
13659
|
-
thread,
|
|
13660
|
-
decision,
|
|
13661
|
-
beforeFirstResponsePost: hooks?.beforeFirstResponsePost
|
|
13662
|
-
})) {
|
|
13663
|
-
await skipSubscribedMessage({
|
|
13664
|
-
thread,
|
|
13665
|
-
message,
|
|
13666
|
-
decision,
|
|
13667
|
-
context,
|
|
13668
|
-
preparedState,
|
|
13669
|
-
userText
|
|
13670
|
-
});
|
|
13671
|
-
return;
|
|
13672
|
-
}
|
|
13673
|
-
if (!decision.shouldReply) {
|
|
13674
|
-
await skipSubscribedMessage({
|
|
13675
|
-
thread,
|
|
13676
|
-
message,
|
|
13677
|
-
decision,
|
|
13678
|
-
context,
|
|
13679
|
-
preparedState,
|
|
13680
|
-
userText
|
|
13681
|
-
});
|
|
13682
|
-
return;
|
|
13683
|
-
}
|
|
13684
13638
|
await deps.withSpan(
|
|
13685
13639
|
"chat.turn",
|
|
13686
13640
|
"chat.turn",
|
|
@@ -13692,6 +13646,78 @@ function createSlackTurnRuntime(deps) {
|
|
|
13692
13646
|
runId
|
|
13693
13647
|
}),
|
|
13694
13648
|
async () => {
|
|
13649
|
+
const rawUserText = message.text;
|
|
13650
|
+
const userText = deps.stripLeadingBotMention(rawUserText, {
|
|
13651
|
+
stripLeadingSlackMentionToken: Boolean(message.isMention)
|
|
13652
|
+
});
|
|
13653
|
+
const context = {
|
|
13654
|
+
threadId,
|
|
13655
|
+
requesterId: message.author.userId,
|
|
13656
|
+
channelId,
|
|
13657
|
+
runId
|
|
13658
|
+
};
|
|
13659
|
+
const preflightDecision = getSubscribedReplyPreflightDecision({
|
|
13660
|
+
botUserName: deps.assistantUserName,
|
|
13661
|
+
rawText: rawUserText,
|
|
13662
|
+
text: userText,
|
|
13663
|
+
isExplicitMention: Boolean(message.isMention)
|
|
13664
|
+
});
|
|
13665
|
+
if (preflightDecision && !preflightDecision.shouldReply) {
|
|
13666
|
+
const reason = preflightDecision.reasonDetail ? `${preflightDecision.reason}:${preflightDecision.reasonDetail}` : preflightDecision.reason;
|
|
13667
|
+
await skipSubscribedMessage({
|
|
13668
|
+
thread,
|
|
13669
|
+
message,
|
|
13670
|
+
decision: { shouldReply: false, reason },
|
|
13671
|
+
context,
|
|
13672
|
+
userText
|
|
13673
|
+
});
|
|
13674
|
+
return;
|
|
13675
|
+
}
|
|
13676
|
+
const preparedState = await deps.prepareTurnState({
|
|
13677
|
+
thread,
|
|
13678
|
+
message,
|
|
13679
|
+
userText,
|
|
13680
|
+
explicitMention: Boolean(message.isMention),
|
|
13681
|
+
context
|
|
13682
|
+
});
|
|
13683
|
+
await deps.persistPreparedState({
|
|
13684
|
+
thread,
|
|
13685
|
+
preparedState
|
|
13686
|
+
});
|
|
13687
|
+
const decision = await deps.decideSubscribedReply({
|
|
13688
|
+
rawText: rawUserText,
|
|
13689
|
+
text: userText,
|
|
13690
|
+
conversationContext: deps.getPreparedConversationContext(preparedState),
|
|
13691
|
+
hasAttachments: message.attachments.length > 0,
|
|
13692
|
+
isExplicitMention: Boolean(message.isMention),
|
|
13693
|
+
context
|
|
13694
|
+
});
|
|
13695
|
+
if (await maybeHandleThreadOptOutDecision({
|
|
13696
|
+
thread,
|
|
13697
|
+
decision,
|
|
13698
|
+
beforeFirstResponsePost: hooks?.beforeFirstResponsePost
|
|
13699
|
+
})) {
|
|
13700
|
+
await skipSubscribedMessage({
|
|
13701
|
+
thread,
|
|
13702
|
+
message,
|
|
13703
|
+
decision,
|
|
13704
|
+
context,
|
|
13705
|
+
preparedState,
|
|
13706
|
+
userText
|
|
13707
|
+
});
|
|
13708
|
+
return;
|
|
13709
|
+
}
|
|
13710
|
+
if (!decision.shouldReply) {
|
|
13711
|
+
await skipSubscribedMessage({
|
|
13712
|
+
thread,
|
|
13713
|
+
message,
|
|
13714
|
+
decision,
|
|
13715
|
+
context,
|
|
13716
|
+
preparedState,
|
|
13717
|
+
userText
|
|
13718
|
+
});
|
|
13719
|
+
return;
|
|
13720
|
+
}
|
|
13695
13721
|
await deps.replyToThread(thread, message, {
|
|
13696
13722
|
explicitMention: Boolean(message.isMention),
|
|
13697
13723
|
preparedState,
|
|
@@ -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();
|
|
@@ -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";
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
disconnectStateAdapter,
|
|
3
3
|
resolveRuntimeDependencySnapshot
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-HZIJ4BSE.js";
|
|
5
5
|
import {
|
|
6
6
|
getPluginProviders,
|
|
7
7
|
getPluginRuntimeDependencies,
|
|
8
8
|
getPluginRuntimePostinstall
|
|
9
|
-
} from "../chunk-
|
|
9
|
+
} from "../chunk-QZRPUFO6.js";
|
|
10
10
|
import "../chunk-Z3YD6NHK.js";
|
|
11
11
|
import "../chunk-XPXD3FCE.js";
|
|
12
12
|
import "../chunk-2KG3PWR4.js";
|