@sentry/junior 0.91.0 → 0.92.1
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/{agent-hooks-MXAF7RQL.js → agent-hooks-KL7I3ZRC.js} +7 -7
- package/dist/api/people/list.d.ts +3 -3
- package/dist/api/people/list.js +15 -15
- package/dist/api/people/list.query.d.ts +2 -2
- package/dist/api/people/profile.d.ts +3 -3
- package/dist/api/people/profile.js +12 -12
- package/dist/api/people/profile.query.d.ts +2 -2
- package/dist/api/people/shared.d.ts +13 -13
- package/dist/api/people/types.d.ts +12 -12
- package/dist/api-reference.d.ts +1 -1
- package/dist/app.js +365 -265
- package/dist/{catalog-runtime-DXE6NXHT.js → catalog-runtime-NZHMSMYC.js} +2 -2
- package/dist/chat/actor.d.ts +75 -0
- package/dist/chat/agent/prompt.d.ts +2 -2
- package/dist/chat/agent/request.d.ts +13 -13
- package/dist/chat/agent/resume.d.ts +5 -4
- package/dist/chat/agent/tools.d.ts +4 -2
- package/dist/chat/capabilities/jr-rpc-command.d.ts +1 -1
- package/dist/chat/conversation-privacy.d.ts +11 -0
- package/dist/chat/conversations/sql/migrations.d.ts +1 -1
- package/dist/chat/conversations/sql/schema/conversations.d.ts +2 -19
- package/dist/chat/conversations/sql/schema.d.ts +2 -19
- package/dist/chat/conversations/sql/store.d.ts +3 -3
- package/dist/chat/conversations/store.d.ts +4 -4
- package/dist/chat/credentials/context.d.ts +4 -4
- package/dist/chat/logging.d.ts +2 -2
- package/dist/chat/no-reply.d.ts +1 -1
- package/dist/chat/oauth-flow.d.ts +1 -1
- package/dist/chat/pi/messages.d.ts +2 -2
- package/dist/chat/pi/transcript.d.ts +15 -0
- package/dist/chat/plugins/agent-hooks.d.ts +5 -3
- package/dist/chat/plugins/credential-hooks.d.ts +2 -8
- package/dist/chat/prompt.d.ts +3 -6
- package/dist/chat/runtime/reply-executor.d.ts +1 -1
- package/dist/chat/runtime/turn-input.d.ts +1 -1
- package/dist/chat/sandbox/egress/schemas.d.ts +2 -2
- package/dist/chat/sandbox/egress/session.d.ts +1 -1
- package/dist/chat/services/context-compaction.d.ts +1 -1
- package/dist/chat/services/conversation-memory.d.ts +1 -1
- package/dist/chat/services/mcp-auth-orchestration.d.ts +1 -1
- package/dist/chat/services/message-actor-identity.d.ts +4 -4
- package/dist/chat/services/pending-auth.d.ts +2 -2
- package/dist/chat/services/plugin-auth-orchestration.d.ts +1 -1
- package/dist/chat/services/provider-default-config.d.ts +1 -1
- package/dist/chat/services/subscribed-decision.d.ts +1 -1
- package/dist/chat/services/turn-result.d.ts +1 -1
- package/dist/chat/services/turn-session-record.d.ts +11 -8
- package/dist/chat/services/turn-thinking-level.d.ts +1 -1
- package/dist/chat/slack/assistant-thread/title.d.ts +1 -1
- package/dist/chat/slack/tools/canvas/create.d.ts +41 -1
- package/dist/chat/slack/tools/canvas/edit.d.ts +60 -1
- package/dist/chat/slack/tools/canvas/read.d.ts +60 -1
- package/dist/chat/slack/tools/canvas/write.d.ts +41 -1
- package/dist/chat/slack/tools/channel-list-messages.d.ts +45 -1
- package/dist/chat/slack/tools/context.d.ts +3 -3
- package/dist/chat/slack/tools/list/add-items.d.ts +42 -1
- package/dist/chat/slack/tools/list/create.d.ts +40 -1
- package/dist/chat/slack/tools/list/get-items.d.ts +40 -1
- package/dist/chat/slack/tools/list/update-item.d.ts +46 -1
- package/dist/chat/slack/tools/message-add-reaction.d.ts +40 -1
- package/dist/chat/slack/tools/send-message.d.ts +45 -1
- package/dist/chat/slack/tools/thread-read.d.ts +44 -1
- package/dist/chat/slack/tools/user-lookup.d.ts +45 -1
- package/dist/chat/slack/user.d.ts +3 -3
- package/dist/chat/slack/vision-context.d.ts +2 -2
- package/dist/chat/sql/schema.d.ts +2 -19
- package/dist/chat/state/conversation-details.d.ts +4 -4
- package/dist/chat/state/conversation.d.ts +1 -1
- package/dist/chat/state/session-log.d.ts +140 -26
- package/dist/chat/state/turn-session.d.ts +18 -5
- package/dist/chat/task-execution/slack-work.d.ts +2 -2
- package/dist/chat/task-execution/state.d.ts +4 -4
- package/dist/chat/tool-support/zod-tool.d.ts +16 -4
- package/dist/chat/tools/advisor/tool.d.ts +41 -1
- package/dist/chat/tools/definition.d.ts +10 -0
- package/dist/chat/tools/execute-tool.d.ts +41 -1
- package/dist/chat/tools/resource-events.d.ts +124 -3
- package/dist/chat/tools/runtime/report-progress.d.ts +40 -1
- package/dist/chat/tools/sandbox/bash.d.ts +41 -1
- package/dist/chat/tools/sandbox/edit-file.d.ts +44 -1
- package/dist/chat/tools/sandbox/find-files.d.ts +42 -1
- package/dist/chat/tools/sandbox/grep.d.ts +46 -1
- package/dist/chat/tools/sandbox/list-dir.d.ts +41 -1
- package/dist/chat/tools/sandbox/read-file.d.ts +42 -1
- package/dist/chat/tools/sandbox/write-file.d.ts +41 -1
- package/dist/chat/tools/search-tools.d.ts +102 -1
- package/dist/chat/tools/skill/call-mcp-tool.d.ts +10 -1
- package/dist/chat/tools/skill/load-skill.d.ts +40 -1
- package/dist/chat/tools/skill/search-mcp-tools.d.ts +100 -1
- package/dist/chat/tools/system-time.d.ts +38 -1
- package/dist/chat/tools/types.d.ts +4 -4
- package/dist/chat/tools/web/fetch-tool.d.ts +41 -1
- package/dist/chat/tools/web/image-generate.d.ts +62 -1
- package/dist/chat/tools/web/search.d.ts +41 -1
- package/dist/{chunk-HXL2ZV74.js → chunk-3F54A3YM.js} +82 -11
- package/dist/{chunk-ZGDTBSQ7.js → chunk-56SIBIVF.js} +930 -660
- package/dist/{chunk-DACFZ5CI.js → chunk-7K3JALTQ.js} +18 -12
- package/dist/{chunk-IRRMABQD.js → chunk-APIVR44P.js} +10 -10
- package/dist/{chunk-XP7F4LYB.js → chunk-BTH37NCU.js} +4 -4
- package/dist/{chunk-5GBUZI6M.js → chunk-H7KUZAMZ.js} +4 -4
- package/dist/{chunk-PIB4EOW6.js → chunk-IWKVXO3F.js} +19 -72
- package/dist/{chunk-TYUXD3FN.js → chunk-MC4ZZE4Q.js} +1 -1
- package/dist/{chunk-2S7M37HY.js → chunk-NIFONS4W.js} +86 -47
- package/dist/{chunk-AOISHLSF.js → chunk-O6ZYIHFC.js} +143 -20
- package/dist/{chunk-GCWD2VHP.js → chunk-OQQU3SD6.js} +285 -124
- package/dist/{chunk-NW7AXDA5.js → chunk-OZJXGX4U.js} +2 -2
- package/dist/{chunk-KC42JAAQ.js → chunk-PFXC67GJ.js} +3 -3
- package/dist/{chunk-QCKGI74V.js → chunk-PGR4WGZW.js} +10 -10
- package/dist/{chunk-ZUK7BL63.js → chunk-S6QKIGRM.js} +66 -54
- package/dist/{chunk-IX76WFJV.js → chunk-TF5VLGA7.js} +10 -10
- package/dist/{chunk-AN2437E3.js → chunk-YTNPU7I2.js} +2 -2
- package/dist/{chunk-3MPOMK3K.js → chunk-YYBX2BD5.js} +61 -3
- package/dist/{chunk-ONFOWI2D.js → chunk-Z4FOYQXW.js} +16 -15
- package/dist/{chunk-RS6ANWVT.js → chunk-ZATRYQLR.js} +1 -1
- package/dist/cli/chat.js +20 -20
- package/dist/cli/check.js +3 -3
- package/dist/cli/plugins.js +9 -9
- package/dist/cli/snapshot-warmup.js +6 -6
- package/dist/cli/upgrade.js +9 -9
- package/dist/{db-CXI7PR5U.js → db-GCK43OO3.js} +4 -4
- package/dist/instrumentation.js +1 -1
- package/dist/reporting/conversations.d.ts +3 -3
- package/dist/reporting.d.ts +1 -1
- package/dist/reporting.js +48 -50
- package/dist/{runner-FKL3RAHA.js → runner-Y73GZ2VE.js} +20 -18
- package/dist/{validation-I7GD2YWS.js → validation-KYAWETI4.js} +3 -3
- package/package.json +6 -6
- package/dist/chat/requester.d.ts +0 -68
|
@@ -11,10 +11,10 @@ import {
|
|
|
11
11
|
persistRunningSessionRecord,
|
|
12
12
|
persistTimeoutSessionRecord,
|
|
13
13
|
persistYieldSessionRecord
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-Z4FOYQXW.js";
|
|
15
15
|
import {
|
|
16
16
|
JUNIOR_THREAD_STATE_TTL_MS
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-PFXC67GJ.js";
|
|
18
18
|
import {
|
|
19
19
|
buildNonInteractiveShellScript,
|
|
20
20
|
createSandboxInstance,
|
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
isSnapshotMissingError,
|
|
24
24
|
resolveRuntimeDependencySnapshot,
|
|
25
25
|
runNonInteractiveCommand
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-H7KUZAMZ.js";
|
|
27
27
|
import {
|
|
28
28
|
JUNIOR_PERSONALITY,
|
|
29
29
|
buildPluginSystemPromptContributions,
|
|
@@ -32,18 +32,18 @@ import {
|
|
|
32
32
|
containsNoReplyMarker,
|
|
33
33
|
formatSlackLink,
|
|
34
34
|
isNoReplyMarker,
|
|
35
|
-
renderCurrentInstruction,
|
|
36
35
|
stripNoReplyMarker
|
|
37
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-IWKVXO3F.js";
|
|
38
37
|
import {
|
|
39
|
-
|
|
38
|
+
instructionActors,
|
|
39
|
+
instructionProvenanceFor,
|
|
40
40
|
loadConnectedMcpProviders,
|
|
41
41
|
recordAuthorizationRequested,
|
|
42
42
|
recordMcpProviderConnected,
|
|
43
43
|
recordSubagentEnded,
|
|
44
44
|
recordSubagentStarted,
|
|
45
45
|
recordToolExecutionStarted
|
|
46
|
-
} from "./chunk-
|
|
46
|
+
} from "./chunk-OQQU3SD6.js";
|
|
47
47
|
import {
|
|
48
48
|
SlackActionError,
|
|
49
49
|
createPluginHookRunner,
|
|
@@ -60,10 +60,10 @@ import {
|
|
|
60
60
|
normalizeSlackConversationId,
|
|
61
61
|
resolveChannelCapabilities,
|
|
62
62
|
withSlackRetries
|
|
63
|
-
} from "./chunk-
|
|
63
|
+
} from "./chunk-7K3JALTQ.js";
|
|
64
64
|
import {
|
|
65
65
|
createPluginLogger
|
|
66
|
-
} from "./chunk-
|
|
66
|
+
} from "./chunk-OZJXGX4U.js";
|
|
67
67
|
import {
|
|
68
68
|
SANDBOX_DATA_ROOT,
|
|
69
69
|
SANDBOX_SKILLS_ROOT,
|
|
@@ -74,11 +74,11 @@ import {
|
|
|
74
74
|
import {
|
|
75
75
|
acquireActiveLock,
|
|
76
76
|
getStateAdapter
|
|
77
|
-
} from "./chunk-
|
|
77
|
+
} from "./chunk-ZATRYQLR.js";
|
|
78
78
|
import {
|
|
79
79
|
getConversationStore,
|
|
80
80
|
getDb
|
|
81
|
-
} from "./chunk-
|
|
81
|
+
} from "./chunk-NIFONS4W.js";
|
|
82
82
|
import {
|
|
83
83
|
GEN_AI_PROVIDER_NAME,
|
|
84
84
|
GEN_AI_SERVER_ADDRESS,
|
|
@@ -87,6 +87,7 @@ import {
|
|
|
87
87
|
botConfig,
|
|
88
88
|
completeObject,
|
|
89
89
|
completeText,
|
|
90
|
+
escapeXml,
|
|
90
91
|
extractAssistantText,
|
|
91
92
|
getGatewayApiKey,
|
|
92
93
|
getPiGatewayApiKey,
|
|
@@ -99,19 +100,22 @@ import {
|
|
|
99
100
|
nextProviderRetry,
|
|
100
101
|
normalizeSlackEmojiName,
|
|
101
102
|
normalizeToolNameFromResult,
|
|
103
|
+
renderCurrentInstruction,
|
|
102
104
|
resolveGatewayModel,
|
|
103
105
|
stripRuntimeTurnContext
|
|
104
|
-
} from "./chunk-
|
|
106
|
+
} from "./chunk-3F54A3YM.js";
|
|
105
107
|
import {
|
|
106
108
|
parseSlackThreadId,
|
|
107
109
|
resolveConversationPrivacy,
|
|
108
110
|
runWithConversationPrivacy,
|
|
111
|
+
toCanonicalInputMessage,
|
|
112
|
+
toCanonicalOutputMessage,
|
|
109
113
|
toGenAiMessageMetadata,
|
|
110
114
|
toGenAiMessagesTraceAttributes,
|
|
111
115
|
toGenAiPayloadMetadata,
|
|
112
116
|
toGenAiPayloadTraceAttributes,
|
|
113
117
|
toGenAiTextMetadata
|
|
114
|
-
} from "./chunk-
|
|
118
|
+
} from "./chunk-YYBX2BD5.js";
|
|
115
119
|
import {
|
|
116
120
|
parseDestination
|
|
117
121
|
} from "./chunk-GHGPTPBL.js";
|
|
@@ -120,20 +124,21 @@ import {
|
|
|
120
124
|
findSkillByName,
|
|
121
125
|
loadSkillsByName,
|
|
122
126
|
parseSkillInvocation
|
|
123
|
-
} from "./chunk-
|
|
127
|
+
} from "./chunk-YTNPU7I2.js";
|
|
124
128
|
import {
|
|
125
129
|
CredentialUnavailableError,
|
|
126
130
|
credentialContextSchema,
|
|
127
131
|
pluginCatalogRuntime,
|
|
128
132
|
resolveAuthTokenPlaceholder,
|
|
129
133
|
resolvePluginCommandEnv
|
|
130
|
-
} from "./chunk-
|
|
134
|
+
} from "./chunk-BTH37NCU.js";
|
|
131
135
|
import {
|
|
132
|
-
|
|
136
|
+
createActor,
|
|
133
137
|
extractGenAiUsageAttributes,
|
|
134
138
|
extractGenAiUsageSummary,
|
|
135
139
|
getLogContextAttributes,
|
|
136
140
|
getTracePropagationHeaders,
|
|
141
|
+
isUserActor,
|
|
137
142
|
logError,
|
|
138
143
|
logException,
|
|
139
144
|
logInfo,
|
|
@@ -145,7 +150,7 @@ import {
|
|
|
145
150
|
setTags,
|
|
146
151
|
summarizeMessageText,
|
|
147
152
|
withSpan
|
|
148
|
-
} from "./chunk-
|
|
153
|
+
} from "./chunk-S6QKIGRM.js";
|
|
149
154
|
import {
|
|
150
155
|
isRecord
|
|
151
156
|
} from "./chunk-OB42YVAE.js";
|
|
@@ -465,7 +470,7 @@ function buildChatStartAttributes(model, context, mode, conversationPrivacy) {
|
|
|
465
470
|
...toGenAiMessagesTraceAttributes("app.ai.input", context.messages)
|
|
466
471
|
};
|
|
467
472
|
const inputMessages = serializeGenAiAttribute(
|
|
468
|
-
mode === "metadata" ? context.messages.map(toGenAiMessageMetadata) : context.messages
|
|
473
|
+
mode === "metadata" ? context.messages.map(toGenAiMessageMetadata) : context.messages.map(toCanonicalInputMessage)
|
|
469
474
|
);
|
|
470
475
|
if (inputMessages) {
|
|
471
476
|
attributes["gen_ai.input.messages"] = inputMessages;
|
|
@@ -486,7 +491,7 @@ function buildChatEndAttributes(message, mode) {
|
|
|
486
491
|
...toGenAiMessagesTraceAttributes("app.ai.output", [message])
|
|
487
492
|
};
|
|
488
493
|
const outputMessages = serializeGenAiAttribute(
|
|
489
|
-
mode === "metadata" ? [toGenAiMessageMetadata(message)] : [message]
|
|
494
|
+
mode === "metadata" ? [toGenAiMessageMetadata(message)] : [toCanonicalOutputMessage(message)]
|
|
490
495
|
);
|
|
491
496
|
if (outputMessages) {
|
|
492
497
|
attributes["gen_ai.output.messages"] = outputMessages;
|
|
@@ -675,8 +680,7 @@ function buildTurnResult(input) {
|
|
|
675
680
|
);
|
|
676
681
|
const canvasCreated = successfulToolNames.has("slackCanvasCreate");
|
|
677
682
|
const reactionPerformed = successfulToolNames.has("addReaction");
|
|
678
|
-
const
|
|
679
|
-
const sideEffectOnlySuccess = markerSideEffectSuccess;
|
|
683
|
+
const silentCompletionSuccess = exactNoReplyMarker;
|
|
680
684
|
const baseDeliveryPlan = {
|
|
681
685
|
mode: "thread",
|
|
682
686
|
postThreadText: true
|
|
@@ -689,7 +693,7 @@ function buildTurnResult(input) {
|
|
|
689
693
|
const markerCategory = reactionPerformed ? "reaction" : "none";
|
|
690
694
|
const markerContext = {
|
|
691
695
|
slackThreadId: correlation?.threadId,
|
|
692
|
-
slackUserId: correlation?.
|
|
696
|
+
slackUserId: correlation?.actorId,
|
|
693
697
|
slackChannelId: correlation?.channelId,
|
|
694
698
|
runId: correlation?.runId,
|
|
695
699
|
assistantUserName,
|
|
@@ -698,29 +702,22 @@ function buildTurnResult(input) {
|
|
|
698
702
|
const markerAttributes = {
|
|
699
703
|
"app.ai.no_reply_marker": true,
|
|
700
704
|
"app.ai.no_reply_marker_category": markerCategory,
|
|
701
|
-
"app.ai.no_reply_marker_accepted":
|
|
705
|
+
"app.ai.no_reply_marker_accepted": !isProviderError
|
|
702
706
|
};
|
|
703
|
-
if (
|
|
707
|
+
if (!isProviderError) {
|
|
704
708
|
logInfo(
|
|
705
709
|
"ai_no_reply_marker_accepted",
|
|
706
710
|
markerContext,
|
|
707
711
|
markerAttributes,
|
|
708
712
|
"No-reply marker suppressed visible thread text"
|
|
709
713
|
);
|
|
710
|
-
} else if (!isProviderError) {
|
|
711
|
-
logWarn(
|
|
712
|
-
"ai_no_reply_marker_rejected",
|
|
713
|
-
markerContext,
|
|
714
|
-
markerAttributes,
|
|
715
|
-
"No-reply marker requires a successful visible side effect"
|
|
716
|
-
);
|
|
717
714
|
}
|
|
718
715
|
} else if (mixedNoReplyMarker) {
|
|
719
716
|
logWarn(
|
|
720
717
|
"ai_no_reply_marker_mixed_text",
|
|
721
718
|
{
|
|
722
719
|
slackThreadId: correlation?.threadId,
|
|
723
|
-
slackUserId: correlation?.
|
|
720
|
+
slackUserId: correlation?.actorId,
|
|
724
721
|
slackChannelId: correlation?.channelId,
|
|
725
722
|
runId: correlation?.runId,
|
|
726
723
|
assistantUserName,
|
|
@@ -733,12 +730,12 @@ function buildTurnResult(input) {
|
|
|
733
730
|
"No-reply marker appeared with visible assistant text"
|
|
734
731
|
);
|
|
735
732
|
}
|
|
736
|
-
if (!primaryText && !
|
|
733
|
+
if (!primaryText && !silentCompletionSuccess && !isProviderError) {
|
|
737
734
|
logWarn(
|
|
738
735
|
"ai_model_response_empty",
|
|
739
736
|
{
|
|
740
737
|
slackThreadId: correlation?.threadId,
|
|
741
|
-
slackUserId: correlation?.
|
|
738
|
+
slackUserId: correlation?.actorId,
|
|
742
739
|
slackChannelId: correlation?.channelId,
|
|
743
740
|
runId: correlation?.runId,
|
|
744
741
|
assistantUserName,
|
|
@@ -756,7 +753,7 @@ function buildTurnResult(input) {
|
|
|
756
753
|
let outcome;
|
|
757
754
|
if (isProviderError) {
|
|
758
755
|
outcome = "provider_error";
|
|
759
|
-
} else if (primaryText ||
|
|
756
|
+
} else if (primaryText || silentCompletionSuccess) {
|
|
760
757
|
outcome = "success";
|
|
761
758
|
} else {
|
|
762
759
|
outcome = "execution_failure";
|
|
@@ -766,7 +763,7 @@ function buildTurnResult(input) {
|
|
|
766
763
|
const escapedOrRawPayload = Boolean(primaryText) && (isExecutionEscapeResponse(primaryText) || isRawToolPayloadResponse(primaryText));
|
|
767
764
|
const resolvedText = escapedOrRawPayload ? "" : responseText;
|
|
768
765
|
const resolvedOutcome = escapedOrRawPayload ? "execution_failure" : outcome;
|
|
769
|
-
const deliveryPlan = resolvedOutcome === "success" && !resolvedText
|
|
766
|
+
const deliveryPlan = resolvedOutcome === "success" && !resolvedText ? {
|
|
770
767
|
...baseDeliveryPlan,
|
|
771
768
|
postThreadText: false
|
|
772
769
|
} : baseDeliveryPlan;
|
|
@@ -939,7 +936,7 @@ async function selectTurnThinkingLevel(args) {
|
|
|
939
936
|
const logContext = {
|
|
940
937
|
slackThreadId: args.context?.threadId,
|
|
941
938
|
slackChannelId: args.context?.channelId,
|
|
942
|
-
slackUserId: args.context?.
|
|
939
|
+
slackUserId: args.context?.actorId,
|
|
943
940
|
runId: args.context?.runId,
|
|
944
941
|
modelId: args.fastModelId
|
|
945
942
|
};
|
|
@@ -962,7 +959,7 @@ async function selectTurnThinkingLevel(args) {
|
|
|
962
959
|
modelId: args.fastModelId,
|
|
963
960
|
threadId: args.context?.threadId ?? "",
|
|
964
961
|
channelId: args.context?.channelId ?? "",
|
|
965
|
-
|
|
962
|
+
actorId: args.context?.actorId ?? "",
|
|
966
963
|
runId: args.context?.runId ?? ""
|
|
967
964
|
},
|
|
968
965
|
prompt
|
|
@@ -1077,25 +1074,38 @@ function getSessionIdentifiers(routing) {
|
|
|
1077
1074
|
sessionId: routing.correlation?.turnId
|
|
1078
1075
|
};
|
|
1079
1076
|
}
|
|
1080
|
-
function
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1077
|
+
function actorFromRouting(routing) {
|
|
1078
|
+
if (routing.dispatch?.actor) {
|
|
1079
|
+
return routing.dispatch.actor;
|
|
1080
|
+
}
|
|
1081
|
+
const userActor = createActor(
|
|
1082
|
+
isUserActor(routing.actor) ? routing.actor : void 0,
|
|
1083
|
+
{
|
|
1084
|
+
platform: (isUserActor(routing.actor) ? routing.actor.platform : void 0) ?? (routing.destination.platform === "slack" ? "slack" : void 0),
|
|
1085
|
+
teamId: (routing.destination.platform === "slack" ? routing.destination.teamId : void 0) ?? routing.correlation?.teamId ?? (routing.actor?.platform === "slack" ? routing.actor.teamId : void 0),
|
|
1086
|
+
userId: routing.correlation?.actorId
|
|
1087
|
+
}
|
|
1088
|
+
);
|
|
1089
|
+
if (userActor) {
|
|
1090
|
+
return userActor;
|
|
1091
|
+
}
|
|
1092
|
+
if (routing.credentialContext && !("type" in routing.credentialContext.actor)) {
|
|
1093
|
+
return routing.credentialContext.actor;
|
|
1094
|
+
}
|
|
1095
|
+
return void 0;
|
|
1086
1096
|
}
|
|
1087
|
-
function
|
|
1088
|
-
const { destination,
|
|
1089
|
-
if (!
|
|
1097
|
+
function assertActorDestinationMatch(routing) {
|
|
1098
|
+
const { destination, actor } = routing;
|
|
1099
|
+
if (!actor) {
|
|
1090
1100
|
return;
|
|
1091
1101
|
}
|
|
1092
|
-
if (
|
|
1102
|
+
if (actor.platform !== destination.platform) {
|
|
1093
1103
|
throw new TypeError(
|
|
1094
|
-
`
|
|
1104
|
+
`Actor platform "${actor.platform}" does not match destination platform "${destination.platform}"`
|
|
1095
1105
|
);
|
|
1096
1106
|
}
|
|
1097
|
-
if (
|
|
1098
|
-
throw new TypeError("Slack
|
|
1107
|
+
if (actor.platform === "slack" && destination.platform === "slack" && actor.teamId !== destination.teamId) {
|
|
1108
|
+
throw new TypeError("Slack actor team does not match destination team");
|
|
1099
1109
|
}
|
|
1100
1110
|
}
|
|
1101
1111
|
function assertCorrelationDestinationMatch(routing) {
|
|
@@ -1571,7 +1581,7 @@ async function assemblePrompt(args) {
|
|
|
1571
1581
|
source
|
|
1572
1582
|
} : void 0,
|
|
1573
1583
|
invocation: args.invocation,
|
|
1574
|
-
|
|
1584
|
+
actor: isUserActor(args.currentActor) ? args.currentActor : void 0,
|
|
1575
1585
|
artifactState: args.artifactState,
|
|
1576
1586
|
configuration: args.configurationValues
|
|
1577
1587
|
}) : null;
|
|
@@ -1739,7 +1749,7 @@ ${usage}
|
|
|
1739
1749
|
const entry = await configuration.set({
|
|
1740
1750
|
key,
|
|
1741
1751
|
value,
|
|
1742
|
-
updatedBy: deps.
|
|
1752
|
+
updatedBy: deps.actorId,
|
|
1743
1753
|
source: "jr-rpc"
|
|
1744
1754
|
});
|
|
1745
1755
|
logInfo(
|
|
@@ -3790,6 +3800,22 @@ function createListDirTool() {
|
|
|
3790
3800
|
// src/chat/tools/web/image-generate.ts
|
|
3791
3801
|
import { z as z9 } from "zod";
|
|
3792
3802
|
var DEFAULT_IMAGE_MODEL = "google/gemini-3-pro-image";
|
|
3803
|
+
var imageGenerateOutputSchema = juniorToolResultSchema.extend({
|
|
3804
|
+
model: z9.string(),
|
|
3805
|
+
prompt: z9.string(),
|
|
3806
|
+
enrichedPrompt: z9.string(),
|
|
3807
|
+
image_count: z9.number().int().nonnegative(),
|
|
3808
|
+
images: z9.array(
|
|
3809
|
+
z9.object({
|
|
3810
|
+
filename: z9.string(),
|
|
3811
|
+
path: z9.string(),
|
|
3812
|
+
attachment_path: z9.string(),
|
|
3813
|
+
media_type: z9.string().optional(),
|
|
3814
|
+
bytes: z9.number().int().nonnegative()
|
|
3815
|
+
}).strict()
|
|
3816
|
+
),
|
|
3817
|
+
delivery: z9.string()
|
|
3818
|
+
}).strict();
|
|
3793
3819
|
var ENRICHMENT_SYSTEM_PROMPT = `You are an image prompt enrichment agent. Your job is to rewrite image generation requests to reflect a specific visual identity and mood.
|
|
3794
3820
|
|
|
3795
3821
|
<personality>
|
|
@@ -3852,7 +3878,7 @@ function createImageGenerateTool(hooks, options = {}, deps = {}) {
|
|
|
3852
3878
|
inputSchema: z9.object({
|
|
3853
3879
|
prompt: z9.string().min(1).max(4e3).describe("Image generation prompt.")
|
|
3854
3880
|
}),
|
|
3855
|
-
outputSchema:
|
|
3881
|
+
outputSchema: imageGenerateOutputSchema,
|
|
3856
3882
|
execute: async ({ prompt }) => {
|
|
3857
3883
|
const fetchImpl = deps.fetch ?? fetch;
|
|
3858
3884
|
const apiKey = getGatewayApiKey();
|
|
@@ -3980,7 +4006,7 @@ function createCallMcpToolTool(mcpToolManager) {
|
|
|
3980
4006
|
description: "Call an active MCP tool by exact tool_name. Use searchMcpTools to discover tool names and schemas; copy required provider fields into arguments. Do not call with only tool_name unless the discovered tool has no arguments. Authorization is handled by the runtime when required.",
|
|
3981
4007
|
inputSchema: z10.object({
|
|
3982
4008
|
tool_name: z10.string().min(1).describe("Exact MCP tool_name from searchMcpTools."),
|
|
3983
|
-
arguments: z10.unknown().describe(
|
|
4009
|
+
arguments: z10.record(z10.string(), z10.unknown()).describe(
|
|
3984
4010
|
'Arguments matching the disclosed MCP tool schema, for example { "query": "..." } when searchMcpTools shows query is required.'
|
|
3985
4011
|
).optional()
|
|
3986
4012
|
}).passthrough(),
|
|
@@ -4219,6 +4245,38 @@ function toActiveMcpCatalogSummaries(toolDefs) {
|
|
|
4219
4245
|
// src/chat/tools/skill/search-mcp-tools.ts
|
|
4220
4246
|
var DEFAULT_MAX_RESULTS = 5;
|
|
4221
4247
|
var MAX_RESULTS = 20;
|
|
4248
|
+
var providerSummarySchema = z12.object({
|
|
4249
|
+
provider: z12.string(),
|
|
4250
|
+
description: z12.string(),
|
|
4251
|
+
active: z12.boolean()
|
|
4252
|
+
}).strict();
|
|
4253
|
+
var mcpCallExampleSchema = z12.object({
|
|
4254
|
+
tool_name: z12.string(),
|
|
4255
|
+
arguments: z12.record(z12.string(), z12.string())
|
|
4256
|
+
}).strict();
|
|
4257
|
+
var exposedToolSummarySchema = z12.object({
|
|
4258
|
+
tool_name: z12.string(),
|
|
4259
|
+
mcp_tool_name: z12.string(),
|
|
4260
|
+
provider: z12.string(),
|
|
4261
|
+
title: z12.string().optional(),
|
|
4262
|
+
description: z12.string(),
|
|
4263
|
+
signature: z12.string(),
|
|
4264
|
+
call: mcpCallExampleSchema,
|
|
4265
|
+
input_schema: z12.record(z12.string(), z12.unknown()),
|
|
4266
|
+
input_schema_summary: z12.string(),
|
|
4267
|
+
output_schema: z12.record(z12.string(), z12.unknown()).optional(),
|
|
4268
|
+
annotations: z12.record(z12.string(), z12.unknown()).optional()
|
|
4269
|
+
}).strict();
|
|
4270
|
+
var searchMcpToolsOutputSchema = juniorToolResultSchema.extend({
|
|
4271
|
+
query: z12.string().nullable(),
|
|
4272
|
+
provider: z12.string().nullable(),
|
|
4273
|
+
total_active_tools: z12.number().int().nonnegative(),
|
|
4274
|
+
returned_tools: z12.number().int().nonnegative(),
|
|
4275
|
+
execution_tool: z12.literal("callMcpTool"),
|
|
4276
|
+
execution_example: mcpCallExampleSchema,
|
|
4277
|
+
available_providers: z12.array(providerSummarySchema),
|
|
4278
|
+
tools: z12.array(exposedToolSummarySchema)
|
|
4279
|
+
}).strict();
|
|
4222
4280
|
function normalize(value) {
|
|
4223
4281
|
return value.toLowerCase().replace(/[^a-z0-9_]+/g, " ").trim();
|
|
4224
4282
|
}
|
|
@@ -4346,7 +4404,7 @@ function createSearchMcpToolsTool(mcpToolManager) {
|
|
|
4346
4404
|
).optional(),
|
|
4347
4405
|
max_results: z12.number().int().min(1).max(MAX_RESULTS).describe("Maximum matching tool descriptors to return.").optional()
|
|
4348
4406
|
}).strict(),
|
|
4349
|
-
outputSchema:
|
|
4407
|
+
outputSchema: searchMcpToolsOutputSchema,
|
|
4350
4408
|
execute: async ({ query, provider, max_results }) => {
|
|
4351
4409
|
if (provider) {
|
|
4352
4410
|
await mcpToolManager.activateProvider(provider);
|
|
@@ -4368,6 +4426,13 @@ function createSearchMcpToolsTool(mcpToolManager) {
|
|
|
4368
4426
|
provider: provider ?? null,
|
|
4369
4427
|
total_active_tools: catalog.length,
|
|
4370
4428
|
returned_tools: matches.length,
|
|
4429
|
+
execution_tool: "callMcpTool",
|
|
4430
|
+
execution_example: {
|
|
4431
|
+
tool_name: "<returned tool_name>",
|
|
4432
|
+
arguments: {
|
|
4433
|
+
"<argument>": "<value from input_schema>"
|
|
4434
|
+
}
|
|
4435
|
+
},
|
|
4371
4436
|
available_providers: providers,
|
|
4372
4437
|
tools: matches.map(toExposedToolSummary)
|
|
4373
4438
|
};
|
|
@@ -5965,6 +6030,17 @@ var editReplacementSchema2 = z22.object({
|
|
|
5965
6030
|
),
|
|
5966
6031
|
newText: z22.string().describe("Replacement Canvas markdown for this edit.")
|
|
5967
6032
|
});
|
|
6033
|
+
var slackCanvasEditOutputSchema = juniorToolResultSchema.extend({
|
|
6034
|
+
canvas_id: z22.string().optional(),
|
|
6035
|
+
title: z22.string().optional(),
|
|
6036
|
+
permalink: z22.string().optional(),
|
|
6037
|
+
diff: z22.string().optional(),
|
|
6038
|
+
first_changed_line: z22.number().int().positive().optional(),
|
|
6039
|
+
replacements: z22.number().int().nonnegative().optional(),
|
|
6040
|
+
normalized_heading_count: z22.number().int().nonnegative().optional(),
|
|
6041
|
+
summary: z22.string().optional(),
|
|
6042
|
+
deduplicated: z22.boolean().optional()
|
|
6043
|
+
}).strict();
|
|
5968
6044
|
function createSlackCanvasEditTool(state) {
|
|
5969
6045
|
return zodTool({
|
|
5970
6046
|
description: "Edit one Slack canvas with exact markdown replacements. Use for precise changes to existing Canvas content; prefer this over slackCanvasWrite for targeted changes. Each oldText must match exactly, be unique, and not overlap another edit. Returns a diff. Multiple changes to the same canvas: use one edits[] call.",
|
|
@@ -5976,7 +6052,7 @@ function createSlackCanvasEditTool(state) {
|
|
|
5976
6052
|
"Exact replacements matched against the current Canvas body, not incrementally."
|
|
5977
6053
|
)
|
|
5978
6054
|
}),
|
|
5979
|
-
outputSchema:
|
|
6055
|
+
outputSchema: slackCanvasEditOutputSchema,
|
|
5980
6056
|
execute: async ({ canvas, edits }) => {
|
|
5981
6057
|
const target = resolveCanvasTarget(canvas);
|
|
5982
6058
|
if (!target.ok) {
|
|
@@ -6051,6 +6127,18 @@ function createSlackCanvasEditTool(state) {
|
|
|
6051
6127
|
|
|
6052
6128
|
// src/chat/slack/tools/canvas/read.ts
|
|
6053
6129
|
import { z as z23 } from "zod";
|
|
6130
|
+
var slackCanvasReadOutputSchema = juniorToolResultSchema.extend({
|
|
6131
|
+
canvas_id: z23.string().optional(),
|
|
6132
|
+
title: z23.string().optional(),
|
|
6133
|
+
permalink: z23.string().optional(),
|
|
6134
|
+
mimetype: z23.string().optional(),
|
|
6135
|
+
filetype: z23.string().optional(),
|
|
6136
|
+
original_byte_length: z23.number().int().nonnegative().optional(),
|
|
6137
|
+
content: z23.string().optional(),
|
|
6138
|
+
start_line: z23.number().int().positive().optional(),
|
|
6139
|
+
end_line: z23.number().int().nonnegative().optional(),
|
|
6140
|
+
total_lines: z23.number().int().nonnegative().optional()
|
|
6141
|
+
}).strict();
|
|
6054
6142
|
function createSlackCanvasReadTool() {
|
|
6055
6143
|
return zodTool({
|
|
6056
6144
|
description: "Read a bounded line range from a Slack canvas as markdown. Use when you need exact Canvas contents to verify facts or make edits safely. Do not use for generic web pages \u2014 use webFetch for those.",
|
|
@@ -6062,7 +6150,7 @@ function createSlackCanvasReadTool() {
|
|
|
6062
6150
|
offset: z23.coerce.number().int().min(1).describe("1-indexed line number to start reading from.").optional(),
|
|
6063
6151
|
limit: z23.coerce.number().int().min(1).describe("Maximum number of lines to read. Defaults to 1000.").optional()
|
|
6064
6152
|
}),
|
|
6065
|
-
outputSchema:
|
|
6153
|
+
outputSchema: slackCanvasReadOutputSchema,
|
|
6066
6154
|
execute: async ({ canvas, offset, limit }) => {
|
|
6067
6155
|
const target = resolveCanvasTarget(canvas);
|
|
6068
6156
|
if (!target.ok) {
|
|
@@ -7362,15 +7450,11 @@ function createAdvisorTool(context) {
|
|
|
7362
7450
|
].join("\n");
|
|
7363
7451
|
const advisorInputMessage = {
|
|
7364
7452
|
role: "user",
|
|
7365
|
-
content: [
|
|
7366
|
-
|
|
7367
|
-
type: "text",
|
|
7368
|
-
text: requestText
|
|
7369
|
-
}
|
|
7370
|
-
]
|
|
7453
|
+
content: [{ type: "text", text: requestText }],
|
|
7454
|
+
timestamp: Date.now()
|
|
7371
7455
|
};
|
|
7372
7456
|
const advisorInputMessagesAttribute = serializeGenAiAttribute(
|
|
7373
|
-
conversationPrivacy !== "public" ? [toGenAiMessageMetadata(advisorInputMessage)] : [advisorInputMessage]
|
|
7457
|
+
conversationPrivacy !== "public" ? [toGenAiMessageMetadata(advisorInputMessage)] : [toCanonicalInputMessage(advisorInputMessage)]
|
|
7374
7458
|
);
|
|
7375
7459
|
return await withSpan(
|
|
7376
7460
|
`invoke_agent ${context.config.modelId}`,
|
|
@@ -7421,7 +7505,7 @@ function createAdvisorTool(context) {
|
|
|
7421
7505
|
const newAdvisorMessages = advisorAgent.state.messages.slice(beforeMessageCount);
|
|
7422
7506
|
const outputMessages = newAdvisorMessages.filter(isAssistantMessage);
|
|
7423
7507
|
const outputMessagesAttribute = serializeGenAiAttribute(
|
|
7424
|
-
conversationPrivacy !== "public" ? outputMessages.map(toGenAiMessageMetadata) : outputMessages
|
|
7508
|
+
conversationPrivacy !== "public" ? outputMessages.map(toGenAiMessageMetadata) : outputMessages.map(toCanonicalOutputMessage)
|
|
7425
7509
|
);
|
|
7426
7510
|
setSpanAttributes({
|
|
7427
7511
|
...outputMessagesAttribute ? { "gen_ai.output.messages": outputMessagesAttribute } : {},
|
|
@@ -8516,7 +8600,7 @@ function upstreamPermissionDeniedText(value) {
|
|
|
8516
8600
|
...sso ? [`Provider SSO: ${sso}`] : [],
|
|
8517
8601
|
...command ? [`Command: ${command}`] : [],
|
|
8518
8602
|
"",
|
|
8519
|
-
"Junior had a credential lease for this grant and forwarded the request. Do not diagnose this as a missing user token or a local Junior runtime block; diagnose provider-side permissions, installation scope, SSO, or
|
|
8603
|
+
"Junior had a credential lease for this grant and forwarded the request. Do not diagnose this as a missing user token or a local Junior runtime block; diagnose provider-side permissions, installation scope, SSO, or actor-provider account access.",
|
|
8520
8604
|
...stderr ? ["", `stderr:
|
|
8521
8605
|
${stderr}`] : [],
|
|
8522
8606
|
...stdout ? ["", `stdout:
|
|
@@ -8586,421 +8670,151 @@ import { PluginToolInputError } from "@sentry/junior-plugin-api";
|
|
|
8586
8670
|
// src/chat/services/plugin-auth-orchestration.ts
|
|
8587
8671
|
import { THREAD_STATE_TTL_MS as THREAD_STATE_TTL_MS2 } from "chat";
|
|
8588
8672
|
|
|
8589
|
-
// src/chat/
|
|
8673
|
+
// src/chat/oauth-flow.ts
|
|
8674
|
+
import { randomBytes } from "crypto";
|
|
8590
8675
|
import {
|
|
8591
8676
|
sourceSchema
|
|
8592
8677
|
} from "@sentry/junior-plugin-api";
|
|
8593
|
-
|
|
8594
|
-
|
|
8595
|
-
|
|
8596
|
-
|
|
8597
|
-
var MCP_AUTH_SESSION_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
8598
|
-
var MCP_AUTH_CREDENTIALS_TTL_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
8599
|
-
var MCP_SERVER_SESSION_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
8600
|
-
function sessionKey(authSessionId) {
|
|
8601
|
-
return `${MCP_AUTH_SESSION_PREFIX}:${authSessionId}`;
|
|
8602
|
-
}
|
|
8603
|
-
function credentialsKey(userId, provider) {
|
|
8604
|
-
return `${MCP_AUTH_CREDENTIALS_PREFIX}:${userId}:${provider}`;
|
|
8605
|
-
}
|
|
8606
|
-
function sessionIndexKey(userId, provider) {
|
|
8607
|
-
return `${MCP_AUTH_SESSION_INDEX_PREFIX}:${userId}:${provider}`;
|
|
8678
|
+
|
|
8679
|
+
// src/chat/oauth-authorization-message.ts
|
|
8680
|
+
function formatOAuthAuthorizationMessage(args) {
|
|
8681
|
+
return `${formatSlackLink(args.authorizationUrl, args.label)}. ${args.completionText}`;
|
|
8608
8682
|
}
|
|
8609
|
-
|
|
8610
|
-
|
|
8683
|
+
|
|
8684
|
+
// src/chat/oauth-flow.ts
|
|
8685
|
+
var OAUTH_STATE_TTL_MS = 10 * 60 * 1e3;
|
|
8686
|
+
function optionalString(value) {
|
|
8687
|
+
return typeof value === "string" ? value : void 0;
|
|
8611
8688
|
}
|
|
8612
|
-
function
|
|
8613
|
-
if (
|
|
8614
|
-
return
|
|
8689
|
+
function parseOAuthStatePayload(value) {
|
|
8690
|
+
if (!isRecord(value)) {
|
|
8691
|
+
return void 0;
|
|
8615
8692
|
}
|
|
8616
|
-
|
|
8617
|
-
|
|
8618
|
-
if (!Array.isArray(parsed)) {
|
|
8619
|
-
return [];
|
|
8620
|
-
}
|
|
8621
|
-
return [
|
|
8622
|
-
...new Set(parsed.filter((id) => typeof id === "string"))
|
|
8623
|
-
];
|
|
8624
|
-
} catch {
|
|
8625
|
-
return [];
|
|
8693
|
+
if (typeof value.userId !== "string" || typeof value.provider !== "string") {
|
|
8694
|
+
return void 0;
|
|
8626
8695
|
}
|
|
8627
|
-
|
|
8628
|
-
|
|
8629
|
-
if (typeof value !== "string") {
|
|
8696
|
+
const destination = parseDestination(value.destination);
|
|
8697
|
+
if (value.destination !== void 0 && !destination) {
|
|
8630
8698
|
return void 0;
|
|
8631
8699
|
}
|
|
8632
|
-
|
|
8633
|
-
|
|
8634
|
-
if (!isRecord(parsed)) {
|
|
8635
|
-
return void 0;
|
|
8636
|
-
}
|
|
8637
|
-
if (typeof parsed.authSessionId !== "string" || typeof parsed.provider !== "string" || typeof parsed.userId !== "string" || typeof parsed.conversationId !== "string" || typeof parsed.sessionId !== "string" || typeof parsed.userMessage !== "string" || typeof parsed.createdAtMs !== "number" || typeof parsed.updatedAtMs !== "number") {
|
|
8638
|
-
return void 0;
|
|
8639
|
-
}
|
|
8640
|
-
const destination = parsed.destination === void 0 ? void 0 : parseDestination(parsed.destination);
|
|
8641
|
-
if (parsed.destination !== void 0 && !destination) {
|
|
8642
|
-
return void 0;
|
|
8643
|
-
}
|
|
8644
|
-
const source = parsed.source === void 0 ? void 0 : sourceSchema.safeParse(parsed.source);
|
|
8645
|
-
if (parsed.source !== void 0 && (!source || !source.success)) {
|
|
8646
|
-
return void 0;
|
|
8647
|
-
}
|
|
8648
|
-
return {
|
|
8649
|
-
authSessionId: parsed.authSessionId,
|
|
8650
|
-
provider: parsed.provider,
|
|
8651
|
-
userId: parsed.userId,
|
|
8652
|
-
conversationId: parsed.conversationId,
|
|
8653
|
-
...destination ? { destination } : {},
|
|
8654
|
-
...source?.success ? { source: source.data } : {},
|
|
8655
|
-
sessionId: parsed.sessionId,
|
|
8656
|
-
userMessage: parsed.userMessage,
|
|
8657
|
-
createdAtMs: parsed.createdAtMs,
|
|
8658
|
-
updatedAtMs: parsed.updatedAtMs,
|
|
8659
|
-
...typeof parsed.channelId === "string" ? { channelId: parsed.channelId } : {},
|
|
8660
|
-
...typeof parsed.threadTs === "string" ? { threadTs: parsed.threadTs } : {},
|
|
8661
|
-
...typeof parsed.toolChannelId === "string" ? { toolChannelId: parsed.toolChannelId } : {},
|
|
8662
|
-
...isRecord(parsed.configuration) ? { configuration: parsed.configuration } : {},
|
|
8663
|
-
...isRecord(parsed.artifactState) ? { artifactState: parsed.artifactState } : {},
|
|
8664
|
-
...typeof parsed.authorizationUrl === "string" ? { authorizationUrl: parsed.authorizationUrl } : {},
|
|
8665
|
-
...typeof parsed.codeVerifier === "string" ? { codeVerifier: parsed.codeVerifier } : {}
|
|
8666
|
-
};
|
|
8667
|
-
} catch {
|
|
8700
|
+
const source = value.source === void 0 ? void 0 : sourceSchema.safeParse(value.source);
|
|
8701
|
+
if (value.source !== void 0 && (!source || !source.success)) {
|
|
8668
8702
|
return void 0;
|
|
8669
8703
|
}
|
|
8670
|
-
|
|
8671
|
-
|
|
8672
|
-
if (typeof value !== "string") {
|
|
8704
|
+
const pendingMessage = optionalString(value.pendingMessage);
|
|
8705
|
+
if (pendingMessage && !source?.success) {
|
|
8673
8706
|
return void 0;
|
|
8674
8707
|
}
|
|
8708
|
+
return {
|
|
8709
|
+
userId: value.userId,
|
|
8710
|
+
provider: value.provider,
|
|
8711
|
+
...optionalString(value.channelId) ? { channelId: optionalString(value.channelId) } : {},
|
|
8712
|
+
...destination ? { destination } : {},
|
|
8713
|
+
...source?.success ? { source: source.data } : {},
|
|
8714
|
+
...optionalString(value.threadTs) ? { threadTs: optionalString(value.threadTs) } : {},
|
|
8715
|
+
...pendingMessage ? { pendingMessage } : {},
|
|
8716
|
+
...isRecord(value.configuration) ? { configuration: value.configuration } : {},
|
|
8717
|
+
...optionalString(value.resumeConversationId) ? { resumeConversationId: optionalString(value.resumeConversationId) } : {},
|
|
8718
|
+
...optionalString(value.resumeSessionId) ? { resumeSessionId: optionalString(value.resumeSessionId) } : {},
|
|
8719
|
+
...optionalString(value.scope) ? { scope: optionalString(value.scope) } : {}
|
|
8720
|
+
};
|
|
8721
|
+
}
|
|
8722
|
+
function formatProviderLabel(provider) {
|
|
8723
|
+
const displayName = pluginCatalogRuntime.getDisplayName(provider);
|
|
8724
|
+
if (!displayName) {
|
|
8725
|
+
throw new Error(`Unknown plugin provider display name: "${provider}"`);
|
|
8726
|
+
}
|
|
8727
|
+
return displayName;
|
|
8728
|
+
}
|
|
8729
|
+
function resolveBaseUrl() {
|
|
8730
|
+
const explicit = process.env.JUNIOR_BASE_URL?.trim();
|
|
8731
|
+
if (explicit) return explicit;
|
|
8732
|
+
const vercelProd = process.env.VERCEL_PROJECT_PRODUCTION_URL?.trim();
|
|
8733
|
+
if (vercelProd) return `https://${vercelProd}`;
|
|
8734
|
+
const vercelUrl = process.env.VERCEL_URL?.trim();
|
|
8735
|
+
if (vercelUrl) return `https://${vercelUrl}`;
|
|
8736
|
+
return void 0;
|
|
8737
|
+
}
|
|
8738
|
+
async function deliverPrivateMessage(input) {
|
|
8739
|
+
let client;
|
|
8675
8740
|
try {
|
|
8676
|
-
|
|
8677
|
-
if (!isRecord(parsed) || typeof parsed.sessionId !== "string" || typeof parsed.updatedAtMs !== "number") {
|
|
8678
|
-
return void 0;
|
|
8679
|
-
}
|
|
8680
|
-
return {
|
|
8681
|
-
sessionId: parsed.sessionId,
|
|
8682
|
-
updatedAtMs: parsed.updatedAtMs
|
|
8683
|
-
};
|
|
8741
|
+
client = getSlackClient();
|
|
8684
8742
|
} catch {
|
|
8685
|
-
|
|
8743
|
+
logWarn(
|
|
8744
|
+
"oauth_private_delivery_skip",
|
|
8745
|
+
{},
|
|
8746
|
+
{ "app.reason": "missing_bot_token" },
|
|
8747
|
+
"Skipped private message delivery \u2014 no SLACK_BOT_TOKEN"
|
|
8748
|
+
);
|
|
8749
|
+
return false;
|
|
8686
8750
|
}
|
|
8687
|
-
|
|
8688
|
-
|
|
8689
|
-
|
|
8690
|
-
|
|
8751
|
+
if (input.channelId) {
|
|
8752
|
+
try {
|
|
8753
|
+
if (isDmChannel(input.channelId)) {
|
|
8754
|
+
await postSlackMessage({
|
|
8755
|
+
channelId: input.channelId,
|
|
8756
|
+
text: input.text,
|
|
8757
|
+
threadTs: input.threadTs
|
|
8758
|
+
});
|
|
8759
|
+
} else {
|
|
8760
|
+
await postSlackEphemeralMessage({
|
|
8761
|
+
channelId: input.channelId,
|
|
8762
|
+
userId: input.userId,
|
|
8763
|
+
text: input.text,
|
|
8764
|
+
threadTs: input.threadTs
|
|
8765
|
+
});
|
|
8766
|
+
}
|
|
8767
|
+
return "in_context";
|
|
8768
|
+
} catch (error) {
|
|
8769
|
+
logWarn(
|
|
8770
|
+
"oauth_private_delivery_failed",
|
|
8771
|
+
{},
|
|
8772
|
+
{
|
|
8773
|
+
"app.slack.error": error instanceof Error ? error.message : String(error),
|
|
8774
|
+
"app.slack.channel": input.channelId
|
|
8775
|
+
},
|
|
8776
|
+
"Private message delivery failed, falling back to DM"
|
|
8777
|
+
);
|
|
8778
|
+
}
|
|
8691
8779
|
}
|
|
8692
8780
|
try {
|
|
8693
|
-
const
|
|
8694
|
-
|
|
8695
|
-
|
|
8781
|
+
const dmChannelId = (await withSlackRetries(
|
|
8782
|
+
() => client.conversations.open({ users: input.userId }),
|
|
8783
|
+
3,
|
|
8784
|
+
{
|
|
8785
|
+
action: "conversations.open",
|
|
8786
|
+
spanAttributes: { "app.slack.user_id": input.userId }
|
|
8787
|
+
}
|
|
8788
|
+
)).channel?.id;
|
|
8789
|
+
if (!dmChannelId) {
|
|
8790
|
+
logWarn(
|
|
8791
|
+
"oauth_dm_fallback_failed",
|
|
8792
|
+
{},
|
|
8793
|
+
{ "app.reason": "no_dm_channel_id" },
|
|
8794
|
+
"conversations.open returned no channel ID"
|
|
8795
|
+
);
|
|
8796
|
+
return false;
|
|
8696
8797
|
}
|
|
8798
|
+
await postSlackMessage({ channelId: dmChannelId, text: input.text });
|
|
8799
|
+
return "fallback_dm";
|
|
8800
|
+
} catch (error) {
|
|
8801
|
+
logWarn(
|
|
8802
|
+
"oauth_dm_fallback_failed",
|
|
8803
|
+
{},
|
|
8804
|
+
{
|
|
8805
|
+
"app.slack.error": error instanceof Error ? error.message : String(error)
|
|
8806
|
+
},
|
|
8807
|
+
"DM fallback delivery failed"
|
|
8808
|
+
);
|
|
8809
|
+
return false;
|
|
8810
|
+
}
|
|
8811
|
+
}
|
|
8812
|
+
async function startOAuthFlow(provider, input) {
|
|
8813
|
+
const providerConfig = pluginCatalogRuntime.getOAuthConfig(provider);
|
|
8814
|
+
if (!providerConfig) {
|
|
8697
8815
|
return {
|
|
8698
|
-
|
|
8699
|
-
|
|
8700
|
-
} : {},
|
|
8701
|
-
...isRecord(parsed.discoveryState) ? {
|
|
8702
|
-
discoveryState: parsed.discoveryState
|
|
8703
|
-
} : {},
|
|
8704
|
-
...isRecord(parsed.tokens) ? { tokens: parsed.tokens } : {}
|
|
8705
|
-
};
|
|
8706
|
-
} catch {
|
|
8707
|
-
return void 0;
|
|
8708
|
-
}
|
|
8709
|
-
}
|
|
8710
|
-
async function getConnectedStateAdapter() {
|
|
8711
|
-
const stateAdapter = getStateAdapter();
|
|
8712
|
-
await stateAdapter.connect();
|
|
8713
|
-
return stateAdapter;
|
|
8714
|
-
}
|
|
8715
|
-
async function getMcpAuthSession(authSessionId) {
|
|
8716
|
-
const stateAdapter = await getConnectedStateAdapter();
|
|
8717
|
-
return parseMcpAuthSession(await stateAdapter.get(sessionKey(authSessionId)));
|
|
8718
|
-
}
|
|
8719
|
-
async function putMcpAuthSession(session, ttlMs2 = MCP_AUTH_SESSION_TTL_MS) {
|
|
8720
|
-
const stateAdapter = await getConnectedStateAdapter();
|
|
8721
|
-
await stateAdapter.set(
|
|
8722
|
-
sessionKey(session.authSessionId),
|
|
8723
|
-
JSON.stringify(session),
|
|
8724
|
-
ttlMs2
|
|
8725
|
-
);
|
|
8726
|
-
const nextIndex = parseSessionIndex(
|
|
8727
|
-
await stateAdapter.get(sessionIndexKey(session.userId, session.provider))
|
|
8728
|
-
);
|
|
8729
|
-
if (!nextIndex.includes(session.authSessionId)) {
|
|
8730
|
-
nextIndex.push(session.authSessionId);
|
|
8731
|
-
}
|
|
8732
|
-
await stateAdapter.set(
|
|
8733
|
-
sessionIndexKey(session.userId, session.provider),
|
|
8734
|
-
JSON.stringify(nextIndex),
|
|
8735
|
-
ttlMs2
|
|
8736
|
-
);
|
|
8737
|
-
}
|
|
8738
|
-
async function patchMcpAuthSession(authSessionId, patch) {
|
|
8739
|
-
const current = await getMcpAuthSession(authSessionId);
|
|
8740
|
-
if (!current) {
|
|
8741
|
-
throw new Error(`Unknown MCP auth session: ${authSessionId}`);
|
|
8742
|
-
}
|
|
8743
|
-
const next = {
|
|
8744
|
-
...current,
|
|
8745
|
-
...patch,
|
|
8746
|
-
authSessionId: current.authSessionId,
|
|
8747
|
-
provider: current.provider,
|
|
8748
|
-
userId: current.userId,
|
|
8749
|
-
conversationId: current.conversationId,
|
|
8750
|
-
...current.destination ? { destination: current.destination } : {},
|
|
8751
|
-
sessionId: current.sessionId,
|
|
8752
|
-
userMessage: current.userMessage,
|
|
8753
|
-
createdAtMs: current.createdAtMs,
|
|
8754
|
-
updatedAtMs: Date.now()
|
|
8755
|
-
};
|
|
8756
|
-
await putMcpAuthSession(next);
|
|
8757
|
-
return next;
|
|
8758
|
-
}
|
|
8759
|
-
async function deleteMcpAuthSession(authSessionId) {
|
|
8760
|
-
const stateAdapter = await getConnectedStateAdapter();
|
|
8761
|
-
const current = parseMcpAuthSession(
|
|
8762
|
-
await stateAdapter.get(sessionKey(authSessionId))
|
|
8763
|
-
);
|
|
8764
|
-
await stateAdapter.delete(sessionKey(authSessionId));
|
|
8765
|
-
if (!current) {
|
|
8766
|
-
return;
|
|
8767
|
-
}
|
|
8768
|
-
const nextIndex = parseSessionIndex(
|
|
8769
|
-
await stateAdapter.get(sessionIndexKey(current.userId, current.provider))
|
|
8770
|
-
).filter((id) => id !== authSessionId);
|
|
8771
|
-
if (nextIndex.length > 0) {
|
|
8772
|
-
await stateAdapter.set(
|
|
8773
|
-
sessionIndexKey(current.userId, current.provider),
|
|
8774
|
-
JSON.stringify(nextIndex),
|
|
8775
|
-
MCP_AUTH_SESSION_TTL_MS
|
|
8776
|
-
);
|
|
8777
|
-
return;
|
|
8778
|
-
}
|
|
8779
|
-
await stateAdapter.delete(sessionIndexKey(current.userId, current.provider));
|
|
8780
|
-
}
|
|
8781
|
-
async function deleteMcpAuthSessionsForUserProvider(userId, provider) {
|
|
8782
|
-
const stateAdapter = await getConnectedStateAdapter();
|
|
8783
|
-
const indexKey = sessionIndexKey(userId, provider);
|
|
8784
|
-
const authSessionIds = parseSessionIndex(await stateAdapter.get(indexKey));
|
|
8785
|
-
for (const authSessionId of authSessionIds) {
|
|
8786
|
-
await stateAdapter.delete(sessionKey(authSessionId));
|
|
8787
|
-
}
|
|
8788
|
-
await stateAdapter.delete(indexKey);
|
|
8789
|
-
}
|
|
8790
|
-
async function getLatestMcpAuthSessionForUserProvider(userId, provider) {
|
|
8791
|
-
const stateAdapter = await getConnectedStateAdapter();
|
|
8792
|
-
const authSessionIds = parseSessionIndex(
|
|
8793
|
-
await stateAdapter.get(sessionIndexKey(userId, provider))
|
|
8794
|
-
);
|
|
8795
|
-
let latestSession;
|
|
8796
|
-
for (const authSessionId of authSessionIds) {
|
|
8797
|
-
const session = parseMcpAuthSession(
|
|
8798
|
-
await stateAdapter.get(sessionKey(authSessionId))
|
|
8799
|
-
);
|
|
8800
|
-
if (!session) {
|
|
8801
|
-
continue;
|
|
8802
|
-
}
|
|
8803
|
-
if (!latestSession || session.updatedAtMs > latestSession.updatedAtMs) {
|
|
8804
|
-
latestSession = session;
|
|
8805
|
-
}
|
|
8806
|
-
}
|
|
8807
|
-
return latestSession;
|
|
8808
|
-
}
|
|
8809
|
-
async function getMcpStoredOAuthCredentials(userId, provider) {
|
|
8810
|
-
const stateAdapter = await getConnectedStateAdapter();
|
|
8811
|
-
return parseStoredCredentials(
|
|
8812
|
-
await stateAdapter.get(credentialsKey(userId, provider))
|
|
8813
|
-
);
|
|
8814
|
-
}
|
|
8815
|
-
async function putMcpStoredOAuthCredentials(userId, provider, value, ttlMs2 = MCP_AUTH_CREDENTIALS_TTL_MS) {
|
|
8816
|
-
const stateAdapter = await getConnectedStateAdapter();
|
|
8817
|
-
await stateAdapter.set(
|
|
8818
|
-
credentialsKey(userId, provider),
|
|
8819
|
-
JSON.stringify(value),
|
|
8820
|
-
ttlMs2
|
|
8821
|
-
);
|
|
8822
|
-
}
|
|
8823
|
-
async function deleteMcpStoredOAuthCredentials(userId, provider) {
|
|
8824
|
-
const stateAdapter = await getConnectedStateAdapter();
|
|
8825
|
-
await stateAdapter.delete(credentialsKey(userId, provider));
|
|
8826
|
-
}
|
|
8827
|
-
async function getMcpServerSessionId(userId, provider) {
|
|
8828
|
-
const stateAdapter = await getConnectedStateAdapter();
|
|
8829
|
-
return parseServerSession(
|
|
8830
|
-
await stateAdapter.get(serverSessionKey(userId, provider))
|
|
8831
|
-
)?.sessionId;
|
|
8832
|
-
}
|
|
8833
|
-
async function putMcpServerSessionId(userId, provider, sessionId, ttlMs2 = MCP_SERVER_SESSION_TTL_MS) {
|
|
8834
|
-
const stateAdapter = await getConnectedStateAdapter();
|
|
8835
|
-
await stateAdapter.set(
|
|
8836
|
-
serverSessionKey(userId, provider),
|
|
8837
|
-
JSON.stringify({
|
|
8838
|
-
sessionId,
|
|
8839
|
-
updatedAtMs: Date.now()
|
|
8840
|
-
}),
|
|
8841
|
-
ttlMs2
|
|
8842
|
-
);
|
|
8843
|
-
}
|
|
8844
|
-
async function deleteMcpServerSessionId(userId, provider) {
|
|
8845
|
-
const stateAdapter = await getConnectedStateAdapter();
|
|
8846
|
-
await stateAdapter.delete(serverSessionKey(userId, provider));
|
|
8847
|
-
}
|
|
8848
|
-
|
|
8849
|
-
// src/chat/credentials/unlink-provider.ts
|
|
8850
|
-
async function unlinkProvider(userId, provider, userTokenStore) {
|
|
8851
|
-
await Promise.all([
|
|
8852
|
-
userTokenStore.delete(userId, provider),
|
|
8853
|
-
deleteMcpStoredOAuthCredentials(userId, provider),
|
|
8854
|
-
deleteMcpServerSessionId(userId, provider),
|
|
8855
|
-
deleteMcpAuthSessionsForUserProvider(userId, provider)
|
|
8856
|
-
]);
|
|
8857
|
-
}
|
|
8858
|
-
|
|
8859
|
-
// src/chat/oauth-flow.ts
|
|
8860
|
-
import { randomBytes } from "crypto";
|
|
8861
|
-
import {
|
|
8862
|
-
sourceSchema as sourceSchema2
|
|
8863
|
-
} from "@sentry/junior-plugin-api";
|
|
8864
|
-
|
|
8865
|
-
// src/chat/oauth-authorization-message.ts
|
|
8866
|
-
function formatOAuthAuthorizationMessage(args) {
|
|
8867
|
-
return `${formatSlackLink(args.authorizationUrl, args.label)}. ${args.completionText}`;
|
|
8868
|
-
}
|
|
8869
|
-
|
|
8870
|
-
// src/chat/oauth-flow.ts
|
|
8871
|
-
var OAUTH_STATE_TTL_MS = 10 * 60 * 1e3;
|
|
8872
|
-
function optionalString(value) {
|
|
8873
|
-
return typeof value === "string" ? value : void 0;
|
|
8874
|
-
}
|
|
8875
|
-
function parseOAuthStatePayload(value) {
|
|
8876
|
-
if (!isRecord(value)) {
|
|
8877
|
-
return void 0;
|
|
8878
|
-
}
|
|
8879
|
-
if (typeof value.userId !== "string" || typeof value.provider !== "string") {
|
|
8880
|
-
return void 0;
|
|
8881
|
-
}
|
|
8882
|
-
const destination = parseDestination(value.destination);
|
|
8883
|
-
if (value.destination !== void 0 && !destination) {
|
|
8884
|
-
return void 0;
|
|
8885
|
-
}
|
|
8886
|
-
const source = value.source === void 0 ? void 0 : sourceSchema2.safeParse(value.source);
|
|
8887
|
-
if (value.source !== void 0 && (!source || !source.success)) {
|
|
8888
|
-
return void 0;
|
|
8889
|
-
}
|
|
8890
|
-
const pendingMessage = optionalString(value.pendingMessage);
|
|
8891
|
-
if (pendingMessage && !source?.success) {
|
|
8892
|
-
return void 0;
|
|
8893
|
-
}
|
|
8894
|
-
return {
|
|
8895
|
-
userId: value.userId,
|
|
8896
|
-
provider: value.provider,
|
|
8897
|
-
...optionalString(value.channelId) ? { channelId: optionalString(value.channelId) } : {},
|
|
8898
|
-
...destination ? { destination } : {},
|
|
8899
|
-
...source?.success ? { source: source.data } : {},
|
|
8900
|
-
...optionalString(value.threadTs) ? { threadTs: optionalString(value.threadTs) } : {},
|
|
8901
|
-
...pendingMessage ? { pendingMessage } : {},
|
|
8902
|
-
...isRecord(value.configuration) ? { configuration: value.configuration } : {},
|
|
8903
|
-
...optionalString(value.resumeConversationId) ? { resumeConversationId: optionalString(value.resumeConversationId) } : {},
|
|
8904
|
-
...optionalString(value.resumeSessionId) ? { resumeSessionId: optionalString(value.resumeSessionId) } : {},
|
|
8905
|
-
...optionalString(value.scope) ? { scope: optionalString(value.scope) } : {}
|
|
8906
|
-
};
|
|
8907
|
-
}
|
|
8908
|
-
function formatProviderLabel(provider) {
|
|
8909
|
-
const displayName = pluginCatalogRuntime.getDisplayName(provider);
|
|
8910
|
-
if (!displayName) {
|
|
8911
|
-
throw new Error(`Unknown plugin provider display name: "${provider}"`);
|
|
8912
|
-
}
|
|
8913
|
-
return displayName;
|
|
8914
|
-
}
|
|
8915
|
-
function resolveBaseUrl() {
|
|
8916
|
-
const explicit = process.env.JUNIOR_BASE_URL?.trim();
|
|
8917
|
-
if (explicit) return explicit;
|
|
8918
|
-
const vercelProd = process.env.VERCEL_PROJECT_PRODUCTION_URL?.trim();
|
|
8919
|
-
if (vercelProd) return `https://${vercelProd}`;
|
|
8920
|
-
const vercelUrl = process.env.VERCEL_URL?.trim();
|
|
8921
|
-
if (vercelUrl) return `https://${vercelUrl}`;
|
|
8922
|
-
return void 0;
|
|
8923
|
-
}
|
|
8924
|
-
async function deliverPrivateMessage(input) {
|
|
8925
|
-
let client;
|
|
8926
|
-
try {
|
|
8927
|
-
client = getSlackClient();
|
|
8928
|
-
} catch {
|
|
8929
|
-
logWarn(
|
|
8930
|
-
"oauth_private_delivery_skip",
|
|
8931
|
-
{},
|
|
8932
|
-
{ "app.reason": "missing_bot_token" },
|
|
8933
|
-
"Skipped private message delivery \u2014 no SLACK_BOT_TOKEN"
|
|
8934
|
-
);
|
|
8935
|
-
return false;
|
|
8936
|
-
}
|
|
8937
|
-
if (input.channelId) {
|
|
8938
|
-
try {
|
|
8939
|
-
if (isDmChannel(input.channelId)) {
|
|
8940
|
-
await postSlackMessage({
|
|
8941
|
-
channelId: input.channelId,
|
|
8942
|
-
text: input.text,
|
|
8943
|
-
threadTs: input.threadTs
|
|
8944
|
-
});
|
|
8945
|
-
} else {
|
|
8946
|
-
await postSlackEphemeralMessage({
|
|
8947
|
-
channelId: input.channelId,
|
|
8948
|
-
userId: input.userId,
|
|
8949
|
-
text: input.text,
|
|
8950
|
-
threadTs: input.threadTs
|
|
8951
|
-
});
|
|
8952
|
-
}
|
|
8953
|
-
return "in_context";
|
|
8954
|
-
} catch (error) {
|
|
8955
|
-
logWarn(
|
|
8956
|
-
"oauth_private_delivery_failed",
|
|
8957
|
-
{},
|
|
8958
|
-
{
|
|
8959
|
-
"app.slack.error": error instanceof Error ? error.message : String(error),
|
|
8960
|
-
"app.slack.channel": input.channelId
|
|
8961
|
-
},
|
|
8962
|
-
"Private message delivery failed, falling back to DM"
|
|
8963
|
-
);
|
|
8964
|
-
}
|
|
8965
|
-
}
|
|
8966
|
-
try {
|
|
8967
|
-
const dmChannelId = (await withSlackRetries(
|
|
8968
|
-
() => client.conversations.open({ users: input.userId }),
|
|
8969
|
-
3,
|
|
8970
|
-
{
|
|
8971
|
-
action: "conversations.open",
|
|
8972
|
-
spanAttributes: { "app.slack.user_id": input.userId }
|
|
8973
|
-
}
|
|
8974
|
-
)).channel?.id;
|
|
8975
|
-
if (!dmChannelId) {
|
|
8976
|
-
logWarn(
|
|
8977
|
-
"oauth_dm_fallback_failed",
|
|
8978
|
-
{},
|
|
8979
|
-
{ "app.reason": "no_dm_channel_id" },
|
|
8980
|
-
"conversations.open returned no channel ID"
|
|
8981
|
-
);
|
|
8982
|
-
return false;
|
|
8983
|
-
}
|
|
8984
|
-
await postSlackMessage({ channelId: dmChannelId, text: input.text });
|
|
8985
|
-
return "fallback_dm";
|
|
8986
|
-
} catch (error) {
|
|
8987
|
-
logWarn(
|
|
8988
|
-
"oauth_dm_fallback_failed",
|
|
8989
|
-
{},
|
|
8990
|
-
{
|
|
8991
|
-
"app.slack.error": error instanceof Error ? error.message : String(error)
|
|
8992
|
-
},
|
|
8993
|
-
"DM fallback delivery failed"
|
|
8994
|
-
);
|
|
8995
|
-
return false;
|
|
8996
|
-
}
|
|
8997
|
-
}
|
|
8998
|
-
async function startOAuthFlow(provider, input) {
|
|
8999
|
-
const providerConfig = pluginCatalogRuntime.getOAuthConfig(provider);
|
|
9000
|
-
if (!providerConfig) {
|
|
9001
|
-
return {
|
|
9002
|
-
ok: false,
|
|
9003
|
-
error: `Provider "${provider}" does not support OAuth authorization`
|
|
8816
|
+
ok: false,
|
|
8817
|
+
error: `Provider "${provider}" does not support OAuth authorization`
|
|
9004
8818
|
};
|
|
9005
8819
|
}
|
|
9006
8820
|
const clientId = process.env[providerConfig.clientIdEnv]?.trim();
|
|
@@ -9023,7 +8837,7 @@ async function startOAuthFlow(provider, input) {
|
|
|
9023
8837
|
await getStateAdapter().set(
|
|
9024
8838
|
`oauth-state:${state}`,
|
|
9025
8839
|
{
|
|
9026
|
-
userId: input.
|
|
8840
|
+
userId: input.actorId,
|
|
9027
8841
|
provider,
|
|
9028
8842
|
...input.channelId ? { channelId: input.channelId } : {},
|
|
9029
8843
|
...input.destination ? { destination: input.destination } : {},
|
|
@@ -9066,7 +8880,7 @@ async function startOAuthFlow(provider, input) {
|
|
|
9066
8880
|
delivery: await deliverPrivateMessage({
|
|
9067
8881
|
channelId: input.channelId,
|
|
9068
8882
|
threadTs: input.threadTs,
|
|
9069
|
-
userId: input.
|
|
8883
|
+
userId: input.actorId,
|
|
9070
8884
|
text: formatOAuthAuthorizationMessage({
|
|
9071
8885
|
authorizationUrl,
|
|
9072
8886
|
label: `Click here to link your ${formatProviderLabel(provider)} account`,
|
|
@@ -9181,7 +8995,7 @@ function createPluginAuthOrchestration(input) {
|
|
|
9181
8995
|
if (pendingPause) {
|
|
9182
8996
|
throw pendingPause;
|
|
9183
8997
|
}
|
|
9184
|
-
if (!input.
|
|
8998
|
+
if (!input.actorId || !pluginCatalogRuntime.getOAuthConfig(provider)) {
|
|
9185
8999
|
throw new Error(`Cannot start plugin authorization for ${provider}`);
|
|
9186
9000
|
}
|
|
9187
9001
|
if (input.authorizationFlowMode === "disabled") {
|
|
@@ -9198,13 +9012,13 @@ function createPluginAuthOrchestration(input) {
|
|
|
9198
9012
|
pendingAuth: input.pendingAuth,
|
|
9199
9013
|
kind: "plugin",
|
|
9200
9014
|
provider,
|
|
9201
|
-
|
|
9015
|
+
actorId: input.actorId,
|
|
9202
9016
|
sessionId: input.sessionId,
|
|
9203
9017
|
...options?.scope ? { scope: options.scope } : {}
|
|
9204
9018
|
}) : false;
|
|
9205
9019
|
if (!reusingPendingLink) {
|
|
9206
9020
|
const oauthResult = await startOAuthFlow(provider, {
|
|
9207
|
-
|
|
9021
|
+
actorId: input.actorId,
|
|
9208
9022
|
channelId: input.channelId,
|
|
9209
9023
|
destination: input.destination,
|
|
9210
9024
|
source: input.source,
|
|
@@ -9224,14 +9038,11 @@ function createPluginAuthOrchestration(input) {
|
|
|
9224
9038
|
);
|
|
9225
9039
|
}
|
|
9226
9040
|
}
|
|
9227
|
-
if (options?.unlinkExistingProvider && input.requesterId && input.userTokenStore) {
|
|
9228
|
-
await unlinkProvider(input.requesterId, provider, input.userTokenStore);
|
|
9229
|
-
}
|
|
9230
9041
|
if (input.sessionId && recordPendingAuth) {
|
|
9231
9042
|
await recordPendingAuth({
|
|
9232
9043
|
kind: "plugin",
|
|
9233
9044
|
provider,
|
|
9234
|
-
|
|
9045
|
+
actorId: input.actorId,
|
|
9235
9046
|
...options?.scope ? { scope: options.scope } : {},
|
|
9236
9047
|
sessionId: input.sessionId,
|
|
9237
9048
|
linkSentAtMs: reusingPendingLink ? input.pendingAuth.linkSentAtMs : Date.now()
|
|
@@ -9242,7 +9053,7 @@ function createPluginAuthOrchestration(input) {
|
|
|
9242
9053
|
conversationId: input.conversationId,
|
|
9243
9054
|
kind: "plugin",
|
|
9244
9055
|
provider,
|
|
9245
|
-
|
|
9056
|
+
actorId: input.actorId,
|
|
9246
9057
|
authorizationId: authorizationId({
|
|
9247
9058
|
kind: "plugin",
|
|
9248
9059
|
provider,
|
|
@@ -9279,7 +9090,7 @@ function createPluginAuthOrchestration(input) {
|
|
|
9279
9090
|
signal.message ?? `${formatProviderLabel(provider)} credentials are required but no OAuth flow is available for this provider.`
|
|
9280
9091
|
);
|
|
9281
9092
|
}
|
|
9282
|
-
if (!input.
|
|
9093
|
+
if (!input.actorId || !input.userTokenStore) {
|
|
9283
9094
|
if (input.authorizationFlowMode === "disabled") {
|
|
9284
9095
|
throw new AuthorizationFlowDisabledError("plugin", provider);
|
|
9285
9096
|
}
|
|
@@ -9294,10 +9105,10 @@ function createPluginAuthOrchestration(input) {
|
|
|
9294
9105
|
signal.message ?? `${formatProviderLabel(provider)} credentials are required but the provider is not configured for OAuth.`
|
|
9295
9106
|
);
|
|
9296
9107
|
}
|
|
9297
|
-
await startAuthorizationPause(
|
|
9298
|
-
|
|
9299
|
-
|
|
9300
|
-
|
|
9108
|
+
await startAuthorizationPause(
|
|
9109
|
+
authorization.provider,
|
|
9110
|
+
authorization.scope ? { scope: authorization.scope } : void 0
|
|
9111
|
+
);
|
|
9301
9112
|
},
|
|
9302
9113
|
getPendingPause: () => pendingPause
|
|
9303
9114
|
};
|
|
@@ -9438,9 +9249,50 @@ import { z as z39 } from "zod";
|
|
|
9438
9249
|
var SEARCH_TOOLS_NAME = "searchTools";
|
|
9439
9250
|
var DEFAULT_MAX_RESULTS2 = 5;
|
|
9440
9251
|
var MAX_RESULTS3 = 20;
|
|
9252
|
+
var MODEL_VISIBLE_DESCRIPTION_CAP = 180;
|
|
9253
|
+
var searchToolsSourceSchema = z39.object({
|
|
9254
|
+
id: z39.string(),
|
|
9255
|
+
description: z39.string()
|
|
9256
|
+
}).strict();
|
|
9257
|
+
var toolCallExampleSchema = z39.object({
|
|
9258
|
+
tool_name: z39.string(),
|
|
9259
|
+
arguments: z39.record(z39.string(), z39.string())
|
|
9260
|
+
}).strict();
|
|
9261
|
+
var searchToolsToolSchema = z39.object({
|
|
9262
|
+
tool_name: z39.string(),
|
|
9263
|
+
description: z39.string(),
|
|
9264
|
+
exposure: z39.enum(["direct", "deferred", "modelOnly", "hidden"]),
|
|
9265
|
+
source: z39.string().optional(),
|
|
9266
|
+
signature: z39.string(),
|
|
9267
|
+
call: toolCallExampleSchema,
|
|
9268
|
+
input_schema: z39.unknown(),
|
|
9269
|
+
input_schema_summary: z39.string(),
|
|
9270
|
+
call_notes: z39.array(z39.string()),
|
|
9271
|
+
annotations: z39.record(z39.string(), z39.unknown())
|
|
9272
|
+
}).strict();
|
|
9273
|
+
var searchToolsOutputSchema = juniorToolResultSchema.extend({
|
|
9274
|
+
query: z39.string().nullable(),
|
|
9275
|
+
source: z39.string().nullable(),
|
|
9276
|
+
sources: z39.array(searchToolsSourceSchema),
|
|
9277
|
+
total_catalog_tools: z39.number().int().nonnegative(),
|
|
9278
|
+
total_eligible_tools: z39.number().int().nonnegative(),
|
|
9279
|
+
total_matches: z39.number().int().nonnegative(),
|
|
9280
|
+
returned_tools: z39.number().int().nonnegative(),
|
|
9281
|
+
execution_tool: z39.literal("executeTool"),
|
|
9282
|
+
execution_example: toolCallExampleSchema,
|
|
9283
|
+
tools: z39.array(searchToolsToolSchema)
|
|
9284
|
+
}).strict();
|
|
9441
9285
|
function normalize2(value) {
|
|
9442
9286
|
return value.toLowerCase().replace(/[^a-z0-9_]+/g, " ").trim();
|
|
9443
9287
|
}
|
|
9288
|
+
function summarizeModelVisibleDescription(description) {
|
|
9289
|
+
const paragraph = description.split(/\n\s*\n/).map((part) => part.trim()).find(Boolean) ?? "";
|
|
9290
|
+
const normalized = paragraph.replace(/\s+/g, " ").trim();
|
|
9291
|
+
if (normalized.length <= MODEL_VISIBLE_DESCRIPTION_CAP) {
|
|
9292
|
+
return normalized;
|
|
9293
|
+
}
|
|
9294
|
+
return `${normalized.slice(0, MODEL_VISIBLE_DESCRIPTION_CAP - 3).trimEnd()}...`;
|
|
9295
|
+
}
|
|
9444
9296
|
function schemaText(schema) {
|
|
9445
9297
|
try {
|
|
9446
9298
|
return JSON.stringify(schema);
|
|
@@ -9455,6 +9307,8 @@ function searchableToolText2(name, definition) {
|
|
|
9455
9307
|
definition.identity?.id,
|
|
9456
9308
|
definition.identity?.name,
|
|
9457
9309
|
definition.identity?.plugin,
|
|
9310
|
+
definition.source?.id,
|
|
9311
|
+
definition.source?.description,
|
|
9458
9312
|
definition.description,
|
|
9459
9313
|
definition.promptSnippet,
|
|
9460
9314
|
...definition.promptGuidelines ?? [],
|
|
@@ -9463,15 +9317,16 @@ function searchableToolText2(name, definition) {
|
|
|
9463
9317
|
].filter(Boolean).join(" ")
|
|
9464
9318
|
);
|
|
9465
9319
|
}
|
|
9466
|
-
function searchCatalogTools(tools, query) {
|
|
9320
|
+
function searchCatalogTools(tools, query, source) {
|
|
9467
9321
|
const entries = Object.entries(tools).sort(
|
|
9468
9322
|
([left], [right]) => left.localeCompare(right)
|
|
9469
9323
|
);
|
|
9324
|
+
const sourceEntries = source ? entries.filter(([, definition]) => definition.source?.id === source) : entries;
|
|
9470
9325
|
if (!normalize2(query)) {
|
|
9471
|
-
return
|
|
9326
|
+
return sourceEntries.map(([name]) => name);
|
|
9472
9327
|
}
|
|
9473
9328
|
const terms = normalize2(query).split(/\s+/).filter(Boolean);
|
|
9474
|
-
return
|
|
9329
|
+
return sourceEntries.filter(([name, definition]) => {
|
|
9475
9330
|
const text = searchableToolText2(name, definition);
|
|
9476
9331
|
return terms.every((term) => text.includes(term));
|
|
9477
9332
|
}).map(([name]) => name);
|
|
@@ -9482,17 +9337,128 @@ function callNotes(definition) {
|
|
|
9482
9337
|
...definition.promptGuidelines?.map((guideline) => guideline.trim()).filter(Boolean) ?? []
|
|
9483
9338
|
];
|
|
9484
9339
|
}
|
|
9485
|
-
function
|
|
9340
|
+
function getSchemaProperties3(schema) {
|
|
9341
|
+
if (!schema || typeof schema !== "object" || !("properties" in schema)) {
|
|
9342
|
+
return {};
|
|
9343
|
+
}
|
|
9344
|
+
const properties = schema.properties;
|
|
9345
|
+
return properties && typeof properties === "object" && !Array.isArray(properties) ? properties : {};
|
|
9346
|
+
}
|
|
9347
|
+
function getRequiredFields3(schema) {
|
|
9348
|
+
if (!schema || typeof schema !== "object" || !("required" in schema)) {
|
|
9349
|
+
return /* @__PURE__ */ new Set();
|
|
9350
|
+
}
|
|
9351
|
+
const required = schema.required;
|
|
9352
|
+
return Array.isArray(required) ? new Set(
|
|
9353
|
+
required.filter((value) => typeof value === "string")
|
|
9354
|
+
) : /* @__PURE__ */ new Set();
|
|
9355
|
+
}
|
|
9356
|
+
function formatSchemaType2(schema) {
|
|
9357
|
+
if (!schema || typeof schema !== "object") {
|
|
9358
|
+
return "unknown";
|
|
9359
|
+
}
|
|
9360
|
+
const typed = schema;
|
|
9361
|
+
const type = typed.type;
|
|
9362
|
+
if (typeof type === "string") {
|
|
9363
|
+
if (type === "array") {
|
|
9364
|
+
return `${formatSchemaType2(typed.items)}[]`;
|
|
9365
|
+
}
|
|
9366
|
+
return type;
|
|
9367
|
+
}
|
|
9368
|
+
if (Array.isArray(type)) {
|
|
9369
|
+
return type.filter((value) => typeof value === "string").join(" | ");
|
|
9370
|
+
}
|
|
9371
|
+
if (Array.isArray(typed.enum) && typed.enum.length > 0) {
|
|
9372
|
+
return typed.enum.map((value) => JSON.stringify(value)).join(" | ");
|
|
9373
|
+
}
|
|
9374
|
+
return "unknown";
|
|
9375
|
+
}
|
|
9376
|
+
function formatArgumentPlaceholder2(name, schema) {
|
|
9377
|
+
const type = formatSchemaType2(schema);
|
|
9378
|
+
if (type === "string") {
|
|
9379
|
+
return `<${name}>`;
|
|
9380
|
+
}
|
|
9381
|
+
if (type === "number" || type === "integer") {
|
|
9382
|
+
return "<number>";
|
|
9383
|
+
}
|
|
9384
|
+
if (type === "boolean") {
|
|
9385
|
+
return "<boolean>";
|
|
9386
|
+
}
|
|
9387
|
+
if (type.endsWith("[]")) {
|
|
9388
|
+
return "<array>";
|
|
9389
|
+
}
|
|
9390
|
+
if (type === "object") {
|
|
9391
|
+
return "<object>";
|
|
9392
|
+
}
|
|
9393
|
+
return `<${type}>`;
|
|
9394
|
+
}
|
|
9395
|
+
function formatToolSignature(name, schema) {
|
|
9396
|
+
const properties = getSchemaProperties3(schema);
|
|
9397
|
+
const required = getRequiredFields3(schema);
|
|
9398
|
+
const fields = Object.entries(properties).map(([field, propertySchema]) => {
|
|
9399
|
+
const marker = required.has(field) ? "" : "?";
|
|
9400
|
+
return `${field}${marker}: ${formatSchemaType2(propertySchema)}`;
|
|
9401
|
+
});
|
|
9402
|
+
return fields.length > 0 ? `${name}({ ${fields.join(", ")} })` : `${name}()`;
|
|
9403
|
+
}
|
|
9404
|
+
function formatToolCallExample(name, schema) {
|
|
9405
|
+
return {
|
|
9406
|
+
tool_name: name,
|
|
9407
|
+
arguments: Object.fromEntries(
|
|
9408
|
+
Object.entries(getSchemaProperties3(schema)).map(
|
|
9409
|
+
([field, propertySchema]) => [
|
|
9410
|
+
field,
|
|
9411
|
+
formatArgumentPlaceholder2(field, propertySchema)
|
|
9412
|
+
]
|
|
9413
|
+
)
|
|
9414
|
+
)
|
|
9415
|
+
};
|
|
9416
|
+
}
|
|
9417
|
+
function sourceSummaries(tools) {
|
|
9418
|
+
const sources = /* @__PURE__ */ new Map();
|
|
9419
|
+
for (const definition of Object.values(tools)) {
|
|
9420
|
+
if (!definition.source) {
|
|
9421
|
+
continue;
|
|
9422
|
+
}
|
|
9423
|
+
sources.set(definition.source.id, {
|
|
9424
|
+
id: definition.source.id,
|
|
9425
|
+
description: summarizeModelVisibleDescription(
|
|
9426
|
+
definition.source.description
|
|
9427
|
+
)
|
|
9428
|
+
});
|
|
9429
|
+
}
|
|
9430
|
+
return [...sources.values()].sort(
|
|
9431
|
+
(left, right) => left.id.localeCompare(right.id)
|
|
9432
|
+
);
|
|
9433
|
+
}
|
|
9434
|
+
function selectedSourceSummaries(tools, matches, requestedSource, knownSources) {
|
|
9435
|
+
if (requestedSource) {
|
|
9436
|
+
return knownSources.filter((source) => source.id === requestedSource);
|
|
9437
|
+
}
|
|
9438
|
+
const matchedSourceIds = new Set(
|
|
9439
|
+
matches.map((name) => tools[name]?.source?.id).filter((source) => Boolean(source))
|
|
9440
|
+
);
|
|
9441
|
+
return knownSources.filter((source) => matchedSourceIds.has(source.id));
|
|
9442
|
+
}
|
|
9443
|
+
function renderSearchToolsDescription(knownSources) {
|
|
9444
|
+
const intro = "Search the executable tool catalog. Deferred tools are grouped by source; use searchTools with source to inspect one source, then executeTool with the exact returned tool_name.";
|
|
9445
|
+
if (knownSources.length === 0) {
|
|
9446
|
+
return intro;
|
|
9447
|
+
}
|
|
9448
|
+
return [
|
|
9449
|
+
intro,
|
|
9450
|
+
"Available sources:",
|
|
9451
|
+
...knownSources.map((source) => `- ${source.id}: ${source.description}`)
|
|
9452
|
+
].join("\n");
|
|
9453
|
+
}
|
|
9454
|
+
function toolMetadata(name, definition, includeSource) {
|
|
9486
9455
|
return {
|
|
9487
9456
|
tool_name: name,
|
|
9488
|
-
description: definition.description,
|
|
9457
|
+
description: summarizeModelVisibleDescription(definition.description),
|
|
9489
9458
|
exposure: effectiveToolExposure(definition),
|
|
9490
|
-
source: definition.
|
|
9491
|
-
|
|
9492
|
-
|
|
9493
|
-
name: definition.identity.name,
|
|
9494
|
-
plugin: definition.identity.plugin
|
|
9495
|
-
} : { type: "core" },
|
|
9459
|
+
...includeSource && definition.source ? { source: definition.source.id } : {},
|
|
9460
|
+
signature: formatToolSignature(name, definition.inputSchema),
|
|
9461
|
+
call: formatToolCallExample(name, definition.inputSchema),
|
|
9496
9462
|
input_schema: definition.inputSchema,
|
|
9497
9463
|
input_schema_summary: summarizeInputSchema(
|
|
9498
9464
|
definition.inputSchema
|
|
@@ -9502,27 +9468,55 @@ function toolMetadata(name, definition) {
|
|
|
9502
9468
|
};
|
|
9503
9469
|
}
|
|
9504
9470
|
function createSearchToolsTool(catalogTools) {
|
|
9471
|
+
const knownSources = sourceSummaries(catalogTools);
|
|
9505
9472
|
return zodTool({
|
|
9506
|
-
description:
|
|
9473
|
+
description: renderSearchToolsDescription(knownSources),
|
|
9507
9474
|
annotations: { readOnlyHint: true, destructiveHint: false },
|
|
9508
9475
|
inputSchema: z39.object({
|
|
9509
9476
|
query: z39.string().nullable().describe(
|
|
9510
9477
|
"Optional search terms describing the tool, owner, action, or arguments needed. Empty string lists catalog tools."
|
|
9511
9478
|
).optional(),
|
|
9479
|
+
source: z39.string().nullable().describe(
|
|
9480
|
+
"Optional source id to search within, such as a plugin source returned in sources."
|
|
9481
|
+
).optional(),
|
|
9512
9482
|
max_results: z39.number().int().min(1).max(MAX_RESULTS3).nullable().describe("Maximum matching catalog tool descriptors to return.").optional()
|
|
9513
9483
|
}).strict(),
|
|
9514
|
-
outputSchema:
|
|
9515
|
-
execute: async ({ query, max_results }) => {
|
|
9484
|
+
outputSchema: searchToolsOutputSchema,
|
|
9485
|
+
execute: async ({ query, source, max_results }) => {
|
|
9516
9486
|
const maxResults = max_results ?? DEFAULT_MAX_RESULTS2;
|
|
9517
|
-
const
|
|
9518
|
-
|
|
9519
|
-
|
|
9487
|
+
const requestedSource = source ?? null;
|
|
9488
|
+
const sourceExists = requestedSource === null || knownSources.some((candidate) => candidate.id === requestedSource);
|
|
9489
|
+
const allMatches = sourceExists ? searchCatalogTools(catalogTools, query ?? "", requestedSource) : [];
|
|
9490
|
+
const matches = allMatches.slice(0, maxResults);
|
|
9491
|
+
const sources = !sourceExists ? knownSources : (query ?? "").trim() ? selectedSourceSummaries(
|
|
9492
|
+
catalogTools,
|
|
9493
|
+
matches,
|
|
9494
|
+
requestedSource,
|
|
9495
|
+
knownSources
|
|
9496
|
+
) : requestedSource ? knownSources.filter(
|
|
9497
|
+
(candidate) => candidate.id === requestedSource
|
|
9498
|
+
) : knownSources;
|
|
9499
|
+
const totalEligibleTools = sourceExists ? searchCatalogTools(catalogTools, "", requestedSource).length : 0;
|
|
9500
|
+
const includePerToolSource = requestedSource === null;
|
|
9501
|
+
const renderedTools = matches.map(
|
|
9502
|
+
(name) => toolMetadata(name, catalogTools[name], includePerToolSource)
|
|
9520
9503
|
);
|
|
9521
9504
|
const data = {
|
|
9522
9505
|
query: query ?? null,
|
|
9506
|
+
source: requestedSource,
|
|
9507
|
+
sources,
|
|
9523
9508
|
total_catalog_tools: Object.keys(catalogTools).length,
|
|
9524
|
-
|
|
9525
|
-
|
|
9509
|
+
total_eligible_tools: totalEligibleTools,
|
|
9510
|
+
total_matches: allMatches.length,
|
|
9511
|
+
returned_tools: renderedTools.length,
|
|
9512
|
+
execution_tool: "executeTool",
|
|
9513
|
+
execution_example: {
|
|
9514
|
+
tool_name: "<returned tool_name>",
|
|
9515
|
+
arguments: {
|
|
9516
|
+
"<argument>": "<value from input_schema>"
|
|
9517
|
+
}
|
|
9518
|
+
},
|
|
9519
|
+
tools: renderedTools
|
|
9526
9520
|
};
|
|
9527
9521
|
return {
|
|
9528
9522
|
ok: true,
|
|
@@ -9734,7 +9728,7 @@ var SANDBOX_EGRESS_LEASE_PREFIX = "sandbox-egress-lease";
|
|
|
9734
9728
|
var DEFAULT_SESSION_TTL_MS = 30 * 60 * 1e3;
|
|
9735
9729
|
function leaseKey(provider, grantName, context) {
|
|
9736
9730
|
const actor = context.credentials.actor;
|
|
9737
|
-
const actorKey =
|
|
9731
|
+
const actorKey = "type" in actor ? `user:${actor.userId}` : `system:${actor.name}`;
|
|
9738
9732
|
return `${SANDBOX_EGRESS_LEASE_PREFIX}:${provider}:${grantName}:${actorKey}:${context.egressId}:${context.contextId}`;
|
|
9739
9733
|
}
|
|
9740
9734
|
function authSignalKey(egressId, access) {
|
|
@@ -11439,132 +11433,392 @@ function createSandboxExecutor(options) {
|
|
|
11439
11433
|
);
|
|
11440
11434
|
return { result };
|
|
11441
11435
|
};
|
|
11442
|
-
const executeFindFilesTool = async (rawInput) => {
|
|
11443
|
-
const pattern = String(rawInput.pattern ?? "");
|
|
11444
|
-
if (!pattern) {
|
|
11445
|
-
throw new ToolInputError("pattern is required");
|
|
11446
|
-
}
|
|
11447
|
-
logSandboxBootRequest("tool.findFiles");
|
|
11448
|
-
const limit = positiveInteger(rawInput.limit);
|
|
11449
|
-
const executors = await sessionManager.ensureToolExecutors();
|
|
11450
|
-
const result = await withSandboxToolSpan(
|
|
11451
|
-
"sandbox.findFiles",
|
|
11452
|
-
"sandbox.fs.find",
|
|
11453
|
-
{
|
|
11454
|
-
"app.sandbox.pattern.length": pattern.length
|
|
11455
|
-
},
|
|
11456
|
-
async () => {
|
|
11457
|
-
const response = await findFiles({
|
|
11458
|
-
fs: executors.fs,
|
|
11459
|
-
pattern,
|
|
11460
|
-
...typeof rawInput.path === "string" ? { path: rawInput.path } : {},
|
|
11461
|
-
...limit ? { limit } : {}
|
|
11462
|
-
});
|
|
11463
|
-
setSpanStatus("ok");
|
|
11464
|
-
return response;
|
|
11465
|
-
}
|
|
11436
|
+
const executeFindFilesTool = async (rawInput) => {
|
|
11437
|
+
const pattern = String(rawInput.pattern ?? "");
|
|
11438
|
+
if (!pattern) {
|
|
11439
|
+
throw new ToolInputError("pattern is required");
|
|
11440
|
+
}
|
|
11441
|
+
logSandboxBootRequest("tool.findFiles");
|
|
11442
|
+
const limit = positiveInteger(rawInput.limit);
|
|
11443
|
+
const executors = await sessionManager.ensureToolExecutors();
|
|
11444
|
+
const result = await withSandboxToolSpan(
|
|
11445
|
+
"sandbox.findFiles",
|
|
11446
|
+
"sandbox.fs.find",
|
|
11447
|
+
{
|
|
11448
|
+
"app.sandbox.pattern.length": pattern.length
|
|
11449
|
+
},
|
|
11450
|
+
async () => {
|
|
11451
|
+
const response = await findFiles({
|
|
11452
|
+
fs: executors.fs,
|
|
11453
|
+
pattern,
|
|
11454
|
+
...typeof rawInput.path === "string" ? { path: rawInput.path } : {},
|
|
11455
|
+
...limit ? { limit } : {}
|
|
11456
|
+
});
|
|
11457
|
+
setSpanStatus("ok");
|
|
11458
|
+
return response;
|
|
11459
|
+
}
|
|
11460
|
+
);
|
|
11461
|
+
return { result };
|
|
11462
|
+
};
|
|
11463
|
+
const executeListDirTool = async (rawInput) => {
|
|
11464
|
+
logSandboxBootRequest("tool.listDir");
|
|
11465
|
+
const limit = positiveInteger(rawInput.limit);
|
|
11466
|
+
const executors = await sessionManager.ensureToolExecutors();
|
|
11467
|
+
const result = await withSandboxToolSpan(
|
|
11468
|
+
"sandbox.listDir",
|
|
11469
|
+
"sandbox.fs.list",
|
|
11470
|
+
{},
|
|
11471
|
+
async () => {
|
|
11472
|
+
const response = await listDir({
|
|
11473
|
+
fs: executors.fs,
|
|
11474
|
+
...typeof rawInput.path === "string" ? { path: rawInput.path } : {},
|
|
11475
|
+
...limit ? { limit } : {}
|
|
11476
|
+
});
|
|
11477
|
+
setSpanStatus("ok");
|
|
11478
|
+
return response;
|
|
11479
|
+
}
|
|
11480
|
+
);
|
|
11481
|
+
return { result };
|
|
11482
|
+
};
|
|
11483
|
+
const execute = async (params) => {
|
|
11484
|
+
const rawInput = params.input ?? {};
|
|
11485
|
+
const bashCommand = params.toolName === "bash" ? String(rawInput.command ?? "").trim() : void 0;
|
|
11486
|
+
if (params.toolName === "bash") {
|
|
11487
|
+
if (!bashCommand) {
|
|
11488
|
+
throw new ToolInputError("command is required");
|
|
11489
|
+
}
|
|
11490
|
+
if (options?.runBashCustomCommand) {
|
|
11491
|
+
const custom = await options.runBashCustomCommand(bashCommand);
|
|
11492
|
+
if (custom.handled) {
|
|
11493
|
+
if (!custom.result) {
|
|
11494
|
+
throw new Error("Custom bash command handler returned no result.");
|
|
11495
|
+
}
|
|
11496
|
+
return { result: bashToolResult(custom.result) };
|
|
11497
|
+
}
|
|
11498
|
+
}
|
|
11499
|
+
return await executeBashTool(rawInput, bashCommand, params.signal);
|
|
11500
|
+
}
|
|
11501
|
+
try {
|
|
11502
|
+
if (params.toolName === "readFile") {
|
|
11503
|
+
return await executeReadFileTool(rawInput);
|
|
11504
|
+
}
|
|
11505
|
+
if (params.toolName === "editFile") {
|
|
11506
|
+
return await executeEditFileTool(rawInput);
|
|
11507
|
+
}
|
|
11508
|
+
if (params.toolName === "grep") {
|
|
11509
|
+
return await executeGrepTool(rawInput);
|
|
11510
|
+
}
|
|
11511
|
+
if (params.toolName === "findFiles") {
|
|
11512
|
+
return await executeFindFilesTool(rawInput);
|
|
11513
|
+
}
|
|
11514
|
+
if (params.toolName === "listDir") {
|
|
11515
|
+
return await executeListDirTool(rawInput);
|
|
11516
|
+
}
|
|
11517
|
+
if (params.toolName === "writeFile") {
|
|
11518
|
+
return await executeWriteFileTool(rawInput);
|
|
11519
|
+
}
|
|
11520
|
+
} catch (error) {
|
|
11521
|
+
if (!isSandboxCommandStreamInterruptedError(error)) {
|
|
11522
|
+
throw error;
|
|
11523
|
+
}
|
|
11524
|
+
return { result: sandboxStreamInterruptedResult(params.toolName) };
|
|
11525
|
+
}
|
|
11526
|
+
throw new Error(`unsupported sandbox tool: ${params.toolName}`);
|
|
11527
|
+
};
|
|
11528
|
+
return {
|
|
11529
|
+
configureSkills(skills) {
|
|
11530
|
+
availableSkills = [...skills];
|
|
11531
|
+
sessionManager.configureSkills(skills);
|
|
11532
|
+
},
|
|
11533
|
+
configureReferenceFiles(files) {
|
|
11534
|
+
referenceFiles = [...files];
|
|
11535
|
+
sessionManager.configureReferenceFiles(files);
|
|
11536
|
+
},
|
|
11537
|
+
getSandboxId() {
|
|
11538
|
+
return sessionManager.getSandboxId();
|
|
11539
|
+
},
|
|
11540
|
+
getDependencyProfileHash() {
|
|
11541
|
+
return sessionManager.getDependencyProfileHash();
|
|
11542
|
+
},
|
|
11543
|
+
canExecute(toolName) {
|
|
11544
|
+
return SANDBOX_TOOL_NAMES.has(toolName);
|
|
11545
|
+
},
|
|
11546
|
+
async createSandbox() {
|
|
11547
|
+
return await sessionManager.createSandbox();
|
|
11548
|
+
},
|
|
11549
|
+
execute,
|
|
11550
|
+
async dispose() {
|
|
11551
|
+
await sessionManager.dispose();
|
|
11552
|
+
}
|
|
11553
|
+
};
|
|
11554
|
+
}
|
|
11555
|
+
|
|
11556
|
+
// src/chat/services/mcp-auth-orchestration.ts
|
|
11557
|
+
import { THREAD_STATE_TTL_MS as THREAD_STATE_TTL_MS3 } from "chat";
|
|
11558
|
+
|
|
11559
|
+
// src/chat/mcp/oauth.ts
|
|
11560
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
11561
|
+
import { StreamableHTTPClientTransport as StreamableHTTPClientTransport2 } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
11562
|
+
|
|
11563
|
+
// src/chat/mcp/auth-store.ts
|
|
11564
|
+
import {
|
|
11565
|
+
sourceSchema as sourceSchema2
|
|
11566
|
+
} from "@sentry/junior-plugin-api";
|
|
11567
|
+
var MCP_AUTH_SESSION_PREFIX = "junior:mcp_auth_session";
|
|
11568
|
+
var MCP_AUTH_CREDENTIALS_PREFIX = "junior:mcp_auth_credentials";
|
|
11569
|
+
var MCP_AUTH_SESSION_INDEX_PREFIX = "junior:mcp_auth_session_index";
|
|
11570
|
+
var MCP_SERVER_SESSION_PREFIX = "junior:mcp_server_session";
|
|
11571
|
+
var MCP_AUTH_SESSION_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
11572
|
+
var MCP_AUTH_CREDENTIALS_TTL_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
11573
|
+
var MCP_SERVER_SESSION_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
11574
|
+
function sessionKey(authSessionId) {
|
|
11575
|
+
return `${MCP_AUTH_SESSION_PREFIX}:${authSessionId}`;
|
|
11576
|
+
}
|
|
11577
|
+
function credentialsKey(userId, provider) {
|
|
11578
|
+
return `${MCP_AUTH_CREDENTIALS_PREFIX}:${userId}:${provider}`;
|
|
11579
|
+
}
|
|
11580
|
+
function sessionIndexKey(userId, provider) {
|
|
11581
|
+
return `${MCP_AUTH_SESSION_INDEX_PREFIX}:${userId}:${provider}`;
|
|
11582
|
+
}
|
|
11583
|
+
function serverSessionKey(userId, provider) {
|
|
11584
|
+
return `${MCP_SERVER_SESSION_PREFIX}:${userId}:${provider}`;
|
|
11585
|
+
}
|
|
11586
|
+
function parseSessionIndex(value) {
|
|
11587
|
+
if (typeof value !== "string") {
|
|
11588
|
+
return [];
|
|
11589
|
+
}
|
|
11590
|
+
try {
|
|
11591
|
+
const parsed = JSON.parse(value);
|
|
11592
|
+
if (!Array.isArray(parsed)) {
|
|
11593
|
+
return [];
|
|
11594
|
+
}
|
|
11595
|
+
return [
|
|
11596
|
+
...new Set(parsed.filter((id) => typeof id === "string"))
|
|
11597
|
+
];
|
|
11598
|
+
} catch {
|
|
11599
|
+
return [];
|
|
11600
|
+
}
|
|
11601
|
+
}
|
|
11602
|
+
function parseMcpAuthSession(value) {
|
|
11603
|
+
if (typeof value !== "string") {
|
|
11604
|
+
return void 0;
|
|
11605
|
+
}
|
|
11606
|
+
try {
|
|
11607
|
+
const parsed = JSON.parse(value);
|
|
11608
|
+
if (!isRecord(parsed)) {
|
|
11609
|
+
return void 0;
|
|
11610
|
+
}
|
|
11611
|
+
if (typeof parsed.authSessionId !== "string" || typeof parsed.provider !== "string" || typeof parsed.userId !== "string" || typeof parsed.conversationId !== "string" || typeof parsed.sessionId !== "string" || typeof parsed.userMessage !== "string" || typeof parsed.createdAtMs !== "number" || typeof parsed.updatedAtMs !== "number") {
|
|
11612
|
+
return void 0;
|
|
11613
|
+
}
|
|
11614
|
+
const destination = parsed.destination === void 0 ? void 0 : parseDestination(parsed.destination);
|
|
11615
|
+
if (parsed.destination !== void 0 && !destination) {
|
|
11616
|
+
return void 0;
|
|
11617
|
+
}
|
|
11618
|
+
const source = parsed.source === void 0 ? void 0 : sourceSchema2.safeParse(parsed.source);
|
|
11619
|
+
if (parsed.source !== void 0 && (!source || !source.success)) {
|
|
11620
|
+
return void 0;
|
|
11621
|
+
}
|
|
11622
|
+
return {
|
|
11623
|
+
authSessionId: parsed.authSessionId,
|
|
11624
|
+
provider: parsed.provider,
|
|
11625
|
+
userId: parsed.userId,
|
|
11626
|
+
conversationId: parsed.conversationId,
|
|
11627
|
+
...destination ? { destination } : {},
|
|
11628
|
+
...source?.success ? { source: source.data } : {},
|
|
11629
|
+
sessionId: parsed.sessionId,
|
|
11630
|
+
userMessage: parsed.userMessage,
|
|
11631
|
+
createdAtMs: parsed.createdAtMs,
|
|
11632
|
+
updatedAtMs: parsed.updatedAtMs,
|
|
11633
|
+
...typeof parsed.channelId === "string" ? { channelId: parsed.channelId } : {},
|
|
11634
|
+
...typeof parsed.threadTs === "string" ? { threadTs: parsed.threadTs } : {},
|
|
11635
|
+
...typeof parsed.toolChannelId === "string" ? { toolChannelId: parsed.toolChannelId } : {},
|
|
11636
|
+
...isRecord(parsed.configuration) ? { configuration: parsed.configuration } : {},
|
|
11637
|
+
...isRecord(parsed.artifactState) ? { artifactState: parsed.artifactState } : {},
|
|
11638
|
+
...typeof parsed.authorizationUrl === "string" ? { authorizationUrl: parsed.authorizationUrl } : {},
|
|
11639
|
+
...typeof parsed.codeVerifier === "string" ? { codeVerifier: parsed.codeVerifier } : {}
|
|
11640
|
+
};
|
|
11641
|
+
} catch {
|
|
11642
|
+
return void 0;
|
|
11643
|
+
}
|
|
11644
|
+
}
|
|
11645
|
+
function parseServerSession(value) {
|
|
11646
|
+
if (typeof value !== "string") {
|
|
11647
|
+
return void 0;
|
|
11648
|
+
}
|
|
11649
|
+
try {
|
|
11650
|
+
const parsed = JSON.parse(value);
|
|
11651
|
+
if (!isRecord(parsed) || typeof parsed.sessionId !== "string" || typeof parsed.updatedAtMs !== "number") {
|
|
11652
|
+
return void 0;
|
|
11653
|
+
}
|
|
11654
|
+
return {
|
|
11655
|
+
sessionId: parsed.sessionId,
|
|
11656
|
+
updatedAtMs: parsed.updatedAtMs
|
|
11657
|
+
};
|
|
11658
|
+
} catch {
|
|
11659
|
+
return void 0;
|
|
11660
|
+
}
|
|
11661
|
+
}
|
|
11662
|
+
function parseStoredCredentials(value) {
|
|
11663
|
+
if (typeof value !== "string") {
|
|
11664
|
+
return void 0;
|
|
11665
|
+
}
|
|
11666
|
+
try {
|
|
11667
|
+
const parsed = JSON.parse(value);
|
|
11668
|
+
if (!isRecord(parsed)) {
|
|
11669
|
+
return void 0;
|
|
11670
|
+
}
|
|
11671
|
+
return {
|
|
11672
|
+
...isRecord(parsed.clientInformation) ? {
|
|
11673
|
+
clientInformation: parsed.clientInformation
|
|
11674
|
+
} : {},
|
|
11675
|
+
...isRecord(parsed.discoveryState) ? {
|
|
11676
|
+
discoveryState: parsed.discoveryState
|
|
11677
|
+
} : {},
|
|
11678
|
+
...isRecord(parsed.tokens) ? { tokens: parsed.tokens } : {}
|
|
11679
|
+
};
|
|
11680
|
+
} catch {
|
|
11681
|
+
return void 0;
|
|
11682
|
+
}
|
|
11683
|
+
}
|
|
11684
|
+
async function getConnectedStateAdapter() {
|
|
11685
|
+
const stateAdapter = getStateAdapter();
|
|
11686
|
+
await stateAdapter.connect();
|
|
11687
|
+
return stateAdapter;
|
|
11688
|
+
}
|
|
11689
|
+
async function getMcpAuthSession(authSessionId) {
|
|
11690
|
+
const stateAdapter = await getConnectedStateAdapter();
|
|
11691
|
+
return parseMcpAuthSession(await stateAdapter.get(sessionKey(authSessionId)));
|
|
11692
|
+
}
|
|
11693
|
+
async function putMcpAuthSession(session, ttlMs2 = MCP_AUTH_SESSION_TTL_MS) {
|
|
11694
|
+
const stateAdapter = await getConnectedStateAdapter();
|
|
11695
|
+
await stateAdapter.set(
|
|
11696
|
+
sessionKey(session.authSessionId),
|
|
11697
|
+
JSON.stringify(session),
|
|
11698
|
+
ttlMs2
|
|
11699
|
+
);
|
|
11700
|
+
const nextIndex = parseSessionIndex(
|
|
11701
|
+
await stateAdapter.get(sessionIndexKey(session.userId, session.provider))
|
|
11702
|
+
);
|
|
11703
|
+
if (!nextIndex.includes(session.authSessionId)) {
|
|
11704
|
+
nextIndex.push(session.authSessionId);
|
|
11705
|
+
}
|
|
11706
|
+
await stateAdapter.set(
|
|
11707
|
+
sessionIndexKey(session.userId, session.provider),
|
|
11708
|
+
JSON.stringify(nextIndex),
|
|
11709
|
+
ttlMs2
|
|
11710
|
+
);
|
|
11711
|
+
}
|
|
11712
|
+
async function patchMcpAuthSession(authSessionId, patch) {
|
|
11713
|
+
const current = await getMcpAuthSession(authSessionId);
|
|
11714
|
+
if (!current) {
|
|
11715
|
+
throw new Error(`Unknown MCP auth session: ${authSessionId}`);
|
|
11716
|
+
}
|
|
11717
|
+
const next = {
|
|
11718
|
+
...current,
|
|
11719
|
+
...patch,
|
|
11720
|
+
authSessionId: current.authSessionId,
|
|
11721
|
+
provider: current.provider,
|
|
11722
|
+
userId: current.userId,
|
|
11723
|
+
conversationId: current.conversationId,
|
|
11724
|
+
...current.destination ? { destination: current.destination } : {},
|
|
11725
|
+
sessionId: current.sessionId,
|
|
11726
|
+
userMessage: current.userMessage,
|
|
11727
|
+
createdAtMs: current.createdAtMs,
|
|
11728
|
+
updatedAtMs: Date.now()
|
|
11729
|
+
};
|
|
11730
|
+
await putMcpAuthSession(next);
|
|
11731
|
+
return next;
|
|
11732
|
+
}
|
|
11733
|
+
async function deleteMcpAuthSession(authSessionId) {
|
|
11734
|
+
const stateAdapter = await getConnectedStateAdapter();
|
|
11735
|
+
const current = parseMcpAuthSession(
|
|
11736
|
+
await stateAdapter.get(sessionKey(authSessionId))
|
|
11737
|
+
);
|
|
11738
|
+
await stateAdapter.delete(sessionKey(authSessionId));
|
|
11739
|
+
if (!current) {
|
|
11740
|
+
return;
|
|
11741
|
+
}
|
|
11742
|
+
const nextIndex = parseSessionIndex(
|
|
11743
|
+
await stateAdapter.get(sessionIndexKey(current.userId, current.provider))
|
|
11744
|
+
).filter((id) => id !== authSessionId);
|
|
11745
|
+
if (nextIndex.length > 0) {
|
|
11746
|
+
await stateAdapter.set(
|
|
11747
|
+
sessionIndexKey(current.userId, current.provider),
|
|
11748
|
+
JSON.stringify(nextIndex),
|
|
11749
|
+
MCP_AUTH_SESSION_TTL_MS
|
|
11466
11750
|
);
|
|
11467
|
-
return
|
|
11468
|
-
}
|
|
11469
|
-
|
|
11470
|
-
|
|
11471
|
-
|
|
11472
|
-
|
|
11473
|
-
|
|
11474
|
-
|
|
11475
|
-
|
|
11476
|
-
|
|
11477
|
-
|
|
11478
|
-
|
|
11479
|
-
|
|
11480
|
-
|
|
11481
|
-
|
|
11482
|
-
|
|
11483
|
-
|
|
11484
|
-
|
|
11485
|
-
|
|
11751
|
+
return;
|
|
11752
|
+
}
|
|
11753
|
+
await stateAdapter.delete(sessionIndexKey(current.userId, current.provider));
|
|
11754
|
+
}
|
|
11755
|
+
async function deleteMcpAuthSessionsForUserProvider(userId, provider) {
|
|
11756
|
+
const stateAdapter = await getConnectedStateAdapter();
|
|
11757
|
+
const indexKey = sessionIndexKey(userId, provider);
|
|
11758
|
+
const authSessionIds = parseSessionIndex(await stateAdapter.get(indexKey));
|
|
11759
|
+
for (const authSessionId of authSessionIds) {
|
|
11760
|
+
await stateAdapter.delete(sessionKey(authSessionId));
|
|
11761
|
+
}
|
|
11762
|
+
await stateAdapter.delete(indexKey);
|
|
11763
|
+
}
|
|
11764
|
+
async function getLatestMcpAuthSessionForUserProvider(userId, provider) {
|
|
11765
|
+
const stateAdapter = await getConnectedStateAdapter();
|
|
11766
|
+
const authSessionIds = parseSessionIndex(
|
|
11767
|
+
await stateAdapter.get(sessionIndexKey(userId, provider))
|
|
11768
|
+
);
|
|
11769
|
+
let latestSession;
|
|
11770
|
+
for (const authSessionId of authSessionIds) {
|
|
11771
|
+
const session = parseMcpAuthSession(
|
|
11772
|
+
await stateAdapter.get(sessionKey(authSessionId))
|
|
11486
11773
|
);
|
|
11487
|
-
|
|
11488
|
-
|
|
11489
|
-
const execute = async (params) => {
|
|
11490
|
-
const rawInput = params.input ?? {};
|
|
11491
|
-
const bashCommand = params.toolName === "bash" ? String(rawInput.command ?? "").trim() : void 0;
|
|
11492
|
-
if (params.toolName === "bash") {
|
|
11493
|
-
if (!bashCommand) {
|
|
11494
|
-
throw new ToolInputError("command is required");
|
|
11495
|
-
}
|
|
11496
|
-
if (options?.runBashCustomCommand) {
|
|
11497
|
-
const custom = await options.runBashCustomCommand(bashCommand);
|
|
11498
|
-
if (custom.handled) {
|
|
11499
|
-
if (!custom.result) {
|
|
11500
|
-
throw new Error("Custom bash command handler returned no result.");
|
|
11501
|
-
}
|
|
11502
|
-
return { result: bashToolResult(custom.result) };
|
|
11503
|
-
}
|
|
11504
|
-
}
|
|
11505
|
-
return await executeBashTool(rawInput, bashCommand, params.signal);
|
|
11506
|
-
}
|
|
11507
|
-
try {
|
|
11508
|
-
if (params.toolName === "readFile") {
|
|
11509
|
-
return await executeReadFileTool(rawInput);
|
|
11510
|
-
}
|
|
11511
|
-
if (params.toolName === "editFile") {
|
|
11512
|
-
return await executeEditFileTool(rawInput);
|
|
11513
|
-
}
|
|
11514
|
-
if (params.toolName === "grep") {
|
|
11515
|
-
return await executeGrepTool(rawInput);
|
|
11516
|
-
}
|
|
11517
|
-
if (params.toolName === "findFiles") {
|
|
11518
|
-
return await executeFindFilesTool(rawInput);
|
|
11519
|
-
}
|
|
11520
|
-
if (params.toolName === "listDir") {
|
|
11521
|
-
return await executeListDirTool(rawInput);
|
|
11522
|
-
}
|
|
11523
|
-
if (params.toolName === "writeFile") {
|
|
11524
|
-
return await executeWriteFileTool(rawInput);
|
|
11525
|
-
}
|
|
11526
|
-
} catch (error) {
|
|
11527
|
-
if (!isSandboxCommandStreamInterruptedError(error)) {
|
|
11528
|
-
throw error;
|
|
11529
|
-
}
|
|
11530
|
-
return { result: sandboxStreamInterruptedResult(params.toolName) };
|
|
11774
|
+
if (!session) {
|
|
11775
|
+
continue;
|
|
11531
11776
|
}
|
|
11532
|
-
|
|
11533
|
-
|
|
11534
|
-
return {
|
|
11535
|
-
configureSkills(skills) {
|
|
11536
|
-
availableSkills = [...skills];
|
|
11537
|
-
sessionManager.configureSkills(skills);
|
|
11538
|
-
},
|
|
11539
|
-
configureReferenceFiles(files) {
|
|
11540
|
-
referenceFiles = [...files];
|
|
11541
|
-
sessionManager.configureReferenceFiles(files);
|
|
11542
|
-
},
|
|
11543
|
-
getSandboxId() {
|
|
11544
|
-
return sessionManager.getSandboxId();
|
|
11545
|
-
},
|
|
11546
|
-
getDependencyProfileHash() {
|
|
11547
|
-
return sessionManager.getDependencyProfileHash();
|
|
11548
|
-
},
|
|
11549
|
-
canExecute(toolName) {
|
|
11550
|
-
return SANDBOX_TOOL_NAMES.has(toolName);
|
|
11551
|
-
},
|
|
11552
|
-
async createSandbox() {
|
|
11553
|
-
return await sessionManager.createSandbox();
|
|
11554
|
-
},
|
|
11555
|
-
execute,
|
|
11556
|
-
async dispose() {
|
|
11557
|
-
await sessionManager.dispose();
|
|
11777
|
+
if (!latestSession || session.updatedAtMs > latestSession.updatedAtMs) {
|
|
11778
|
+
latestSession = session;
|
|
11558
11779
|
}
|
|
11559
|
-
}
|
|
11780
|
+
}
|
|
11781
|
+
return latestSession;
|
|
11782
|
+
}
|
|
11783
|
+
async function getMcpStoredOAuthCredentials(userId, provider) {
|
|
11784
|
+
const stateAdapter = await getConnectedStateAdapter();
|
|
11785
|
+
return parseStoredCredentials(
|
|
11786
|
+
await stateAdapter.get(credentialsKey(userId, provider))
|
|
11787
|
+
);
|
|
11788
|
+
}
|
|
11789
|
+
async function putMcpStoredOAuthCredentials(userId, provider, value, ttlMs2 = MCP_AUTH_CREDENTIALS_TTL_MS) {
|
|
11790
|
+
const stateAdapter = await getConnectedStateAdapter();
|
|
11791
|
+
await stateAdapter.set(
|
|
11792
|
+
credentialsKey(userId, provider),
|
|
11793
|
+
JSON.stringify(value),
|
|
11794
|
+
ttlMs2
|
|
11795
|
+
);
|
|
11796
|
+
}
|
|
11797
|
+
async function deleteMcpStoredOAuthCredentials(userId, provider) {
|
|
11798
|
+
const stateAdapter = await getConnectedStateAdapter();
|
|
11799
|
+
await stateAdapter.delete(credentialsKey(userId, provider));
|
|
11800
|
+
}
|
|
11801
|
+
async function getMcpServerSessionId(userId, provider) {
|
|
11802
|
+
const stateAdapter = await getConnectedStateAdapter();
|
|
11803
|
+
return parseServerSession(
|
|
11804
|
+
await stateAdapter.get(serverSessionKey(userId, provider))
|
|
11805
|
+
)?.sessionId;
|
|
11806
|
+
}
|
|
11807
|
+
async function putMcpServerSessionId(userId, provider, sessionId, ttlMs2 = MCP_SERVER_SESSION_TTL_MS) {
|
|
11808
|
+
const stateAdapter = await getConnectedStateAdapter();
|
|
11809
|
+
await stateAdapter.set(
|
|
11810
|
+
serverSessionKey(userId, provider),
|
|
11811
|
+
JSON.stringify({
|
|
11812
|
+
sessionId,
|
|
11813
|
+
updatedAtMs: Date.now()
|
|
11814
|
+
}),
|
|
11815
|
+
ttlMs2
|
|
11816
|
+
);
|
|
11817
|
+
}
|
|
11818
|
+
async function deleteMcpServerSessionId(userId, provider) {
|
|
11819
|
+
const stateAdapter = await getConnectedStateAdapter();
|
|
11820
|
+
await stateAdapter.delete(serverSessionKey(userId, provider));
|
|
11560
11821
|
}
|
|
11561
|
-
|
|
11562
|
-
// src/chat/services/mcp-auth-orchestration.ts
|
|
11563
|
-
import { THREAD_STATE_TTL_MS as THREAD_STATE_TTL_MS3 } from "chat";
|
|
11564
|
-
|
|
11565
|
-
// src/chat/mcp/oauth.ts
|
|
11566
|
-
import { randomUUID as randomUUID3 } from "crypto";
|
|
11567
|
-
import { StreamableHTTPClientTransport as StreamableHTTPClientTransport2 } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
11568
11822
|
|
|
11569
11823
|
// src/chat/mcp/oauth-provider.ts
|
|
11570
11824
|
function createClientMetadata(callbackUrl) {
|
|
@@ -11853,7 +12107,7 @@ function createMcpAuthOrchestration(input) {
|
|
|
11853
12107
|
let pendingPause;
|
|
11854
12108
|
const authSessionIdsByProvider = /* @__PURE__ */ new Map();
|
|
11855
12109
|
const authProviderFactory = async (plugin) => {
|
|
11856
|
-
if (!input.conversationId || !input.sessionId || !input.
|
|
12110
|
+
if (!input.conversationId || !input.sessionId || !input.actorId) {
|
|
11857
12111
|
return void 0;
|
|
11858
12112
|
}
|
|
11859
12113
|
if (!input.recordPendingAuth && input.authorizationFlowMode !== "disabled") {
|
|
@@ -11867,7 +12121,7 @@ function createMcpAuthOrchestration(input) {
|
|
|
11867
12121
|
destination: input.destination,
|
|
11868
12122
|
source: input.source,
|
|
11869
12123
|
sessionId: input.sessionId,
|
|
11870
|
-
userId: input.
|
|
12124
|
+
userId: input.actorId,
|
|
11871
12125
|
userMessage: input.userMessage,
|
|
11872
12126
|
...input.channelId ? { channelId: input.channelId } : {},
|
|
11873
12127
|
...input.threadTs ? { threadTs: input.threadTs } : {},
|
|
@@ -11885,8 +12139,8 @@ function createMcpAuthOrchestration(input) {
|
|
|
11885
12139
|
const authSessionId = authSessionIdsByProvider.get(provider);
|
|
11886
12140
|
const conversationId = input.conversationId;
|
|
11887
12141
|
const sessionId = input.sessionId;
|
|
11888
|
-
const
|
|
11889
|
-
if (!authSessionId || !conversationId || !sessionId || !
|
|
12142
|
+
const actorId = input.actorId;
|
|
12143
|
+
if (!authSessionId || !conversationId || !sessionId || !actorId) {
|
|
11890
12144
|
throw new Error(
|
|
11891
12145
|
`Missing MCP auth session context for plugin "${provider}"`
|
|
11892
12146
|
);
|
|
@@ -11915,7 +12169,7 @@ function createMcpAuthOrchestration(input) {
|
|
|
11915
12169
|
pendingAuth: input.pendingAuth,
|
|
11916
12170
|
kind: "mcp",
|
|
11917
12171
|
provider,
|
|
11918
|
-
|
|
12172
|
+
actorId,
|
|
11919
12173
|
sessionId
|
|
11920
12174
|
});
|
|
11921
12175
|
const providerLabel = formatProviderLabel(provider);
|
|
@@ -11941,7 +12195,7 @@ function createMcpAuthOrchestration(input) {
|
|
|
11941
12195
|
await recordPendingAuth({
|
|
11942
12196
|
kind: "mcp",
|
|
11943
12197
|
provider,
|
|
11944
|
-
|
|
12198
|
+
actorId,
|
|
11945
12199
|
sessionId,
|
|
11946
12200
|
linkSentAtMs: reusingPendingLink ? input.pendingAuth.linkSentAtMs : Date.now()
|
|
11947
12201
|
});
|
|
@@ -11949,7 +12203,7 @@ function createMcpAuthOrchestration(input) {
|
|
|
11949
12203
|
conversationId,
|
|
11950
12204
|
kind: "mcp",
|
|
11951
12205
|
provider,
|
|
11952
|
-
|
|
12206
|
+
actorId,
|
|
11953
12207
|
authorizationId: authorizationId2({
|
|
11954
12208
|
kind: "mcp",
|
|
11955
12209
|
provider,
|
|
@@ -12111,7 +12365,7 @@ async function issuePluginCredential(input) {
|
|
|
12111
12365
|
if (!plugin || !hook) {
|
|
12112
12366
|
throw new Error(`Plugin "${input.provider}" has no issueCredential hook`);
|
|
12113
12367
|
}
|
|
12114
|
-
const currentUserId = input.actor
|
|
12368
|
+
const currentUserId = "type" in input.actor ? input.actor.userId : void 0;
|
|
12115
12369
|
const credentialSubjectUserId = input.credentialSubject?.userId;
|
|
12116
12370
|
const result = await hook({
|
|
12117
12371
|
...basePluginContext(plugin),
|
|
@@ -13090,10 +13344,11 @@ async function writeSandboxGeneratedArtifacts(sandbox, files) {
|
|
|
13090
13344
|
// src/chat/agent/tools.ts
|
|
13091
13345
|
async function wireAgentTools(args) {
|
|
13092
13346
|
const runSource = args.routing.source;
|
|
13093
|
-
const
|
|
13347
|
+
const authActorId = args.routing.credentialContext && "type" in args.routing.credentialContext.actor ? args.routing.credentialContext.actor.userId : void 0;
|
|
13094
13348
|
const userTokenStore = createUserTokenStore();
|
|
13095
13349
|
const pluginHooks = createPluginHookRunner({
|
|
13096
|
-
|
|
13350
|
+
actor: args.currentActor,
|
|
13351
|
+
actors: args.currentActors
|
|
13097
13352
|
});
|
|
13098
13353
|
const sandboxExecutor = createSandboxExecutor({
|
|
13099
13354
|
sandboxId: args.state.sandbox?.sandboxId,
|
|
@@ -13113,7 +13368,7 @@ async function wireAgentTools(args) {
|
|
|
13113
13368
|
const result = await maybeExecuteJrRpcCustomCommand(command, {
|
|
13114
13369
|
activeSkill: args.skillSandbox.getActiveSkill(),
|
|
13115
13370
|
channelConfiguration: args.policy.channelConfiguration,
|
|
13116
|
-
|
|
13371
|
+
actorId: isUserActor(args.currentActor) ? args.currentActor.userId : void 0,
|
|
13117
13372
|
onConfigurationValueChanged: (key, value) => {
|
|
13118
13373
|
if (value === void 0) {
|
|
13119
13374
|
delete args.configurationValues[key];
|
|
@@ -13137,7 +13392,7 @@ async function wireAgentTools(args) {
|
|
|
13137
13392
|
abortAgent: args.abortAgent,
|
|
13138
13393
|
conversationId: args.sessionConversationId,
|
|
13139
13394
|
sessionId: args.sessionId,
|
|
13140
|
-
|
|
13395
|
+
actorId: authActorId,
|
|
13141
13396
|
channelId: slackChannelId,
|
|
13142
13397
|
destination: args.routing.destination,
|
|
13143
13398
|
source: runSource,
|
|
@@ -13158,7 +13413,7 @@ async function wireAgentTools(args) {
|
|
|
13158
13413
|
abortAgent: args.abortAgent,
|
|
13159
13414
|
conversationId: args.sessionConversationId,
|
|
13160
13415
|
sessionId: args.sessionId,
|
|
13161
|
-
|
|
13416
|
+
actorId: authActorId,
|
|
13162
13417
|
channelId: slackChannelId,
|
|
13163
13418
|
destination: args.routing.destination,
|
|
13164
13419
|
source: runSource,
|
|
@@ -13228,7 +13483,7 @@ async function wireAgentTools(args) {
|
|
|
13228
13483
|
toolRuntimeContext = {
|
|
13229
13484
|
...commonToolRuntimeContext,
|
|
13230
13485
|
destination: toolDestination,
|
|
13231
|
-
|
|
13486
|
+
actor: args.currentActor?.platform === "slack" ? args.currentActor : void 0,
|
|
13232
13487
|
source: runSource
|
|
13233
13488
|
};
|
|
13234
13489
|
} else {
|
|
@@ -13238,7 +13493,7 @@ async function wireAgentTools(args) {
|
|
|
13238
13493
|
toolRuntimeContext = {
|
|
13239
13494
|
...commonToolRuntimeContext,
|
|
13240
13495
|
destination: toolDestination,
|
|
13241
|
-
|
|
13496
|
+
actor: args.currentActor?.platform === "local" ? args.currentActor : void 0,
|
|
13242
13497
|
source: runSource
|
|
13243
13498
|
};
|
|
13244
13499
|
}
|
|
@@ -13413,7 +13668,7 @@ function createResumeState(args) {
|
|
|
13413
13668
|
sessionId: args.sessionId,
|
|
13414
13669
|
loadedSkillNames: args.getLoadedSkillNames(),
|
|
13415
13670
|
logContext: args.logContext,
|
|
13416
|
-
|
|
13671
|
+
actor: args.actor,
|
|
13417
13672
|
...args.surface ? { surface: args.surface } : {}
|
|
13418
13673
|
});
|
|
13419
13674
|
return {
|
|
@@ -13451,7 +13706,7 @@ function createResumeState(args) {
|
|
|
13451
13706
|
await args.durability.onInputCommitted?.();
|
|
13452
13707
|
inputCommitted = true;
|
|
13453
13708
|
},
|
|
13454
|
-
async persistSafeBoundary(messages) {
|
|
13709
|
+
async persistSafeBoundary(messages, trailingMessageProvenance) {
|
|
13455
13710
|
if (!canPersistSession) {
|
|
13456
13711
|
return false;
|
|
13457
13712
|
}
|
|
@@ -13459,6 +13714,7 @@ function createResumeState(args) {
|
|
|
13459
13714
|
...sessionRecordBase(),
|
|
13460
13715
|
sliceId: currentSliceId,
|
|
13461
13716
|
messages,
|
|
13717
|
+
...trailingMessageProvenance ? { trailingMessageProvenance } : {},
|
|
13462
13718
|
...turnStartMessageIndex !== void 0 ? { turnStartMessageIndex } : {}
|
|
13463
13719
|
});
|
|
13464
13720
|
if (!persisted) {
|
|
@@ -13467,8 +13723,11 @@ function createResumeState(args) {
|
|
|
13467
13723
|
latestSafeBoundaryMessages = [...messages];
|
|
13468
13724
|
return true;
|
|
13469
13725
|
},
|
|
13470
|
-
async requireDurableInputCheckpoint(messages) {
|
|
13471
|
-
const persisted = await this.persistSafeBoundary(
|
|
13726
|
+
async requireDurableInputCheckpoint(messages, trailingMessageProvenance) {
|
|
13727
|
+
const persisted = await this.persistSafeBoundary(
|
|
13728
|
+
messages,
|
|
13729
|
+
trailingMessageProvenance
|
|
13730
|
+
);
|
|
13472
13731
|
if (!persisted && args.durability.onInputCommitted) {
|
|
13473
13732
|
throw new TurnInputCommitLostError(
|
|
13474
13733
|
`Durable turn input could not be checkpointed for conversation=${args.sessionConversationId ?? "unknown"} session=${args.sessionId ?? "unknown"}`
|
|
@@ -13627,7 +13886,7 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy) {
|
|
|
13627
13886
|
if (!routing.destination) {
|
|
13628
13887
|
throw new TypeError("Assistant reply generation requires a destination");
|
|
13629
13888
|
}
|
|
13630
|
-
|
|
13889
|
+
assertActorDestinationMatch(routing);
|
|
13631
13890
|
assertCorrelationDestinationMatch(routing);
|
|
13632
13891
|
const replyStartedAtMs = Date.now();
|
|
13633
13892
|
const configuredTurnDeadlineAtMs = replyStartedAtMs + botConfig.turnTimeoutMs;
|
|
@@ -13642,18 +13901,18 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy) {
|
|
|
13642
13901
|
let canRecordMcpProviders = false;
|
|
13643
13902
|
let turnUsage;
|
|
13644
13903
|
let thinkingSelection;
|
|
13645
|
-
const
|
|
13904
|
+
const actor = actorFromRouting(routing);
|
|
13646
13905
|
const surface = surfaceFromRouting(routing);
|
|
13647
13906
|
const runSource = routing.source;
|
|
13648
13907
|
const userInput = input.messageText;
|
|
13649
13908
|
const credentialActor = routing.credentialContext?.actor;
|
|
13650
13909
|
const credentialActorLogContext = credentialActor ? {
|
|
13651
|
-
actorType: credentialActor.type,
|
|
13652
|
-
actorId:
|
|
13910
|
+
actorType: "type" in credentialActor ? credentialActor.type : "system",
|
|
13911
|
+
actorId: "type" in credentialActor ? credentialActor.userId : credentialActor.name
|
|
13653
13912
|
} : {};
|
|
13654
13913
|
const sessionRecordLogContext = {
|
|
13655
13914
|
threadId: routing.correlation?.threadId,
|
|
13656
|
-
|
|
13915
|
+
actorId: routing.correlation?.actorId,
|
|
13657
13916
|
channelId: routing.correlation?.channelId,
|
|
13658
13917
|
runId: routing.correlation?.runId,
|
|
13659
13918
|
...credentialActorLogContext,
|
|
@@ -13689,7 +13948,7 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy) {
|
|
|
13689
13948
|
const spanContext = {
|
|
13690
13949
|
conversationId: sessionConversationId,
|
|
13691
13950
|
slackThreadId: routing.correlation?.threadId,
|
|
13692
|
-
slackUserId: routing.correlation?.
|
|
13951
|
+
slackUserId: routing.correlation?.actorId,
|
|
13693
13952
|
slackChannelId: routing.correlation?.channelId,
|
|
13694
13953
|
runId: routing.correlation?.runId,
|
|
13695
13954
|
...credentialActorLogContext,
|
|
@@ -13733,6 +13992,11 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy) {
|
|
|
13733
13992
|
currentSliceId,
|
|
13734
13993
|
existingSessionRecord
|
|
13735
13994
|
} = await restoreSessionRecord(routing);
|
|
13995
|
+
const committedInstructionProvenance = existingSessionRecord?.piMessageProvenance ? [
|
|
13996
|
+
...existingSessionRecord.piMessageProvenance,
|
|
13997
|
+
...resumedFromSessionRecord ? [] : [instructionProvenanceFor(actor)]
|
|
13998
|
+
] : [instructionProvenanceFor(actor)];
|
|
13999
|
+
const runActors = () => instructionActors(committedInstructionProvenance);
|
|
13736
14000
|
canRecordMcpProviders = Boolean(
|
|
13737
14001
|
sessionRecordState.canUseTurnSession && sessionConversationId && sessionId
|
|
13738
14002
|
);
|
|
@@ -13743,7 +14007,7 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy) {
|
|
|
13743
14007
|
getLoadedSkillNames: () => loadedSkillNamesForResume,
|
|
13744
14008
|
logContext: sessionRecordLogContext,
|
|
13745
14009
|
recordActiveMcpProviders,
|
|
13746
|
-
|
|
14010
|
+
actor,
|
|
13747
14011
|
runSource,
|
|
13748
14012
|
sessionConversationId,
|
|
13749
14013
|
sessionId,
|
|
@@ -13804,7 +14068,7 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy) {
|
|
|
13804
14068
|
context: {
|
|
13805
14069
|
threadId: routing.correlation?.threadId,
|
|
13806
14070
|
channelId: routing.correlation?.channelId,
|
|
13807
|
-
|
|
14071
|
+
actorId: routing.correlation?.actorId,
|
|
13808
14072
|
runId: routing.correlation?.runId
|
|
13809
14073
|
},
|
|
13810
14074
|
currentTurnBlocks: routerBlocks,
|
|
@@ -13813,7 +14077,7 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy) {
|
|
|
13813
14077
|
});
|
|
13814
14078
|
setSpanAttributes({
|
|
13815
14079
|
"gen_ai.request.model": botConfig.modelId,
|
|
13816
|
-
"
|
|
14080
|
+
"gen_ai.request.reasoning.level": thinkingSelection.thinkingLevel,
|
|
13817
14081
|
"app.ai.thinking_level_reason": thinkingSelection.reason,
|
|
13818
14082
|
...thinkingSelection.confidence !== void 0 ? {
|
|
13819
14083
|
"app.ai.thinking_level_confidence": thinkingSelection.confidence
|
|
@@ -13827,7 +14091,7 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy) {
|
|
|
13827
14091
|
setTags({
|
|
13828
14092
|
conversationId: spanContext.conversationId,
|
|
13829
14093
|
slackThreadId: routing.correlation?.threadId,
|
|
13830
|
-
slackUserId: routing.correlation?.
|
|
14094
|
+
slackUserId: routing.correlation?.actorId,
|
|
13831
14095
|
slackChannelId: routing.correlation?.channelId,
|
|
13832
14096
|
runId: routing.correlation?.runId,
|
|
13833
14097
|
...credentialActorLogContext,
|
|
@@ -13837,7 +14101,8 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy) {
|
|
|
13837
14101
|
const wiring = await wireAgentTools({
|
|
13838
14102
|
abortAgent: () => agent?.abort(),
|
|
13839
14103
|
activeSkills,
|
|
13840
|
-
|
|
14104
|
+
currentActor: actor,
|
|
14105
|
+
currentActors: runActors,
|
|
13841
14106
|
artifactStatePatch,
|
|
13842
14107
|
availableSkills,
|
|
13843
14108
|
configurationValues,
|
|
@@ -13879,7 +14144,7 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy) {
|
|
|
13879
14144
|
shouldPromptAgent
|
|
13880
14145
|
} = await assemblePrompt({
|
|
13881
14146
|
activeMcpCatalogs: wiring.activeMcpCatalogs,
|
|
13882
|
-
|
|
14147
|
+
currentActor: actor,
|
|
13883
14148
|
artifactState: state.artifactState,
|
|
13884
14149
|
availableSkills,
|
|
13885
14150
|
configurationValues,
|
|
@@ -13908,10 +14173,13 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy) {
|
|
|
13908
14173
|
if (piMessages.length === 0) {
|
|
13909
14174
|
return;
|
|
13910
14175
|
}
|
|
13911
|
-
await runResume.requireDurableInputCheckpoint(
|
|
13912
|
-
...agent.state.messages,
|
|
13913
|
-
|
|
13914
|
-
|
|
14176
|
+
await runResume.requireDurableInputCheckpoint(
|
|
14177
|
+
[...agent.state.messages, ...piMessages],
|
|
14178
|
+
messages.map((message) => message.provenance)
|
|
14179
|
+
);
|
|
14180
|
+
committedInstructionProvenance.push(
|
|
14181
|
+
...messages.map((message) => message.provenance)
|
|
14182
|
+
);
|
|
13915
14183
|
for (const message of piMessages) {
|
|
13916
14184
|
agent.steer(message);
|
|
13917
14185
|
}
|
|
@@ -14066,7 +14334,7 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy) {
|
|
|
14066
14334
|
"gen_ai.operation.name": "invoke_agent",
|
|
14067
14335
|
"gen_ai.request.model": botConfig.modelId,
|
|
14068
14336
|
...thinkingSelection ? {
|
|
14069
|
-
"
|
|
14337
|
+
"gen_ai.request.reasoning.level": thinkingSelection.thinkingLevel
|
|
14070
14338
|
} : {},
|
|
14071
14339
|
"app.ai.turn_timeout_ms": turnTimeoutBudgetMs,
|
|
14072
14340
|
"app.ai.turn_deadline_remaining_ms": Math.max(
|
|
@@ -14119,7 +14387,7 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy) {
|
|
|
14119
14387
|
);
|
|
14120
14388
|
const outputMessages = newMessages.filter(isAssistantMessage);
|
|
14121
14389
|
const outputMessagesAttribute = serializeGenAiAttribute(
|
|
14122
|
-
conversationPrivacy !== "public" ? outputMessages.map(toGenAiMessageMetadata) : outputMessages
|
|
14390
|
+
conversationPrivacy !== "public" ? outputMessages.map(toGenAiMessageMetadata) : outputMessages.map(toCanonicalOutputMessage)
|
|
14123
14391
|
);
|
|
14124
14392
|
const usageSummary = extractGenAiUsageSummary(
|
|
14125
14393
|
promptResult,
|
|
@@ -14175,7 +14443,7 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy) {
|
|
|
14175
14443
|
...sessionConversationId ? { "app.ai.session.conversation_id": sessionConversationId } : {},
|
|
14176
14444
|
...sessionId ? { "app.ai.turn.session_id": sessionId } : {},
|
|
14177
14445
|
...currentSliceId ? { "app.ai.turn.slice_id": currentSliceId } : {},
|
|
14178
|
-
"
|
|
14446
|
+
"gen_ai.request.reasoning.level": thinkingSelection.thinkingLevel,
|
|
14179
14447
|
...toGenAiMessagesTraceAttributes("app.ai.input", inputMessages),
|
|
14180
14448
|
...inputMessagesAttribute ? { "gen_ai.input.messages": inputMessagesAttribute } : {}
|
|
14181
14449
|
}
|
|
@@ -14233,7 +14501,7 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy) {
|
|
|
14233
14501
|
"assistant_reply_generation_failed",
|
|
14234
14502
|
{
|
|
14235
14503
|
slackThreadId: routing.correlation?.threadId,
|
|
14236
|
-
slackUserId: routing.correlation?.
|
|
14504
|
+
slackUserId: routing.correlation?.actorId,
|
|
14237
14505
|
slackChannelId: routing.correlation?.channelId,
|
|
14238
14506
|
runId: routing.correlation?.runId,
|
|
14239
14507
|
...credentialActorLogContext,
|
|
@@ -14314,9 +14582,6 @@ export {
|
|
|
14314
14582
|
removeReactionFromMessage,
|
|
14315
14583
|
renderSlackLegacyAttachmentText,
|
|
14316
14584
|
appendSlackLegacyAttachmentText,
|
|
14317
|
-
deleteMcpAuthSession,
|
|
14318
|
-
getMcpStoredOAuthCredentials,
|
|
14319
|
-
unlinkProvider,
|
|
14320
14585
|
parseOAuthStatePayload,
|
|
14321
14586
|
formatProviderLabel,
|
|
14322
14587
|
resolveBaseUrl,
|
|
@@ -14327,6 +14592,11 @@ export {
|
|
|
14327
14592
|
normalizeSandboxEgressTracePropagationDomains,
|
|
14328
14593
|
shouldPropagateSandboxEgressTrace,
|
|
14329
14594
|
resolveSandboxEgressProviderForHost,
|
|
14595
|
+
deleteMcpAuthSession,
|
|
14596
|
+
deleteMcpAuthSessionsForUserProvider,
|
|
14597
|
+
getMcpStoredOAuthCredentials,
|
|
14598
|
+
deleteMcpStoredOAuthCredentials,
|
|
14599
|
+
deleteMcpServerSessionId,
|
|
14330
14600
|
finalizeMcpAuthorization,
|
|
14331
14601
|
resolvePluginOAuthAccount,
|
|
14332
14602
|
executeCredentialedEgressRequest,
|