@sentry/junior 0.92.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-BYSSWCNW.js → agent-hooks-KL7I3ZRC.js} +1 -1
- package/dist/app.js +38 -9
- package/dist/chat/agent/tools.d.ts +2 -0
- package/dist/chat/plugins/agent-hooks.d.ts +2 -0
- package/dist/{chunk-7DVIELX3.js → chunk-56SIBIVF.js} +409 -408
- package/dist/{chunk-VY7TVOIK.js → chunk-7K3JALTQ.js} +2 -0
- package/dist/{chunk-BMQ5DXHV.js → chunk-IWKVXO3F.js} +1 -1
- package/dist/{chunk-ACJENBVF.js → chunk-O6ZYIHFC.js} +3 -3
- package/dist/{chunk-7FS3K243.js → chunk-OQQU3SD6.js} +1 -0
- package/dist/{chunk-N25HRI6B.js → chunk-PGR4WGZW.js} +1 -1
- package/dist/{chunk-OJP53WIU.js → chunk-Z4FOYQXW.js} +1 -1
- package/dist/cli/chat.js +7 -7
- package/dist/cli/plugins.js +1 -1
- package/dist/reporting.js +4 -4
- package/dist/{runner-XWTFA26U.js → runner-Y73GZ2VE.js} +4 -4
- package/package.json +5 -5
package/dist/app.js
CHANGED
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
scheduleSessionCompletedPluginTasks,
|
|
18
18
|
updateConversationStats,
|
|
19
19
|
upsertConversationMessage
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-O6ZYIHFC.js";
|
|
21
21
|
import {
|
|
22
22
|
CONVERSATION_WORK_CHECK_IN_INTERVAL_MS,
|
|
23
23
|
CONVERSATION_WORK_STALE_ENQUEUE_MS,
|
|
@@ -60,7 +60,7 @@ import {
|
|
|
60
60
|
resolveSlackChannelTypeFromMessage,
|
|
61
61
|
resolveSlackConversationContext,
|
|
62
62
|
setConversationTitle
|
|
63
|
-
} from "./chunk-
|
|
63
|
+
} from "./chunk-PGR4WGZW.js";
|
|
64
64
|
import {
|
|
65
65
|
validatePluginEgressCredentialHooks,
|
|
66
66
|
validatePluginRegistrations
|
|
@@ -81,6 +81,9 @@ import {
|
|
|
81
81
|
createAgentRunner,
|
|
82
82
|
createUserTokenStore,
|
|
83
83
|
deleteMcpAuthSession,
|
|
84
|
+
deleteMcpAuthSessionsForUserProvider,
|
|
85
|
+
deleteMcpServerSessionId,
|
|
86
|
+
deleteMcpStoredOAuthCredentials,
|
|
84
87
|
deliverResourceEventSubscription,
|
|
85
88
|
executeAgentRun,
|
|
86
89
|
executeCredentialedEgressRequest,
|
|
@@ -102,9 +105,8 @@ import {
|
|
|
102
105
|
setConfigDefaults,
|
|
103
106
|
shouldEmitDevAgentTrace,
|
|
104
107
|
shouldPropagateSandboxEgressTrace,
|
|
105
|
-
startOAuthFlow
|
|
106
|
-
|
|
107
|
-
} from "./chunk-7DVIELX3.js";
|
|
108
|
+
startOAuthFlow
|
|
109
|
+
} from "./chunk-56SIBIVF.js";
|
|
108
110
|
import {
|
|
109
111
|
CooperativeTurnYieldError,
|
|
110
112
|
TurnInputCommitLostError,
|
|
@@ -131,7 +133,7 @@ import {
|
|
|
131
133
|
persistThreadStateById,
|
|
132
134
|
persistYieldSessionRecord,
|
|
133
135
|
startActiveTurn
|
|
134
|
-
} from "./chunk-
|
|
136
|
+
} from "./chunk-Z4FOYQXW.js";
|
|
135
137
|
import {
|
|
136
138
|
JUNIOR_THREAD_STATE_TTL_MS,
|
|
137
139
|
coerceThreadConversationState
|
|
@@ -144,7 +146,7 @@ import {
|
|
|
144
146
|
normalizeSlackStatusText,
|
|
145
147
|
splitSlackReplyText,
|
|
146
148
|
truncateStatusText
|
|
147
|
-
} from "./chunk-
|
|
149
|
+
} from "./chunk-IWKVXO3F.js";
|
|
148
150
|
import {
|
|
149
151
|
abandonAgentTurnSessionRecord,
|
|
150
152
|
commitMessages,
|
|
@@ -157,7 +159,7 @@ import {
|
|
|
157
159
|
loadProjectionWithProvenance,
|
|
158
160
|
recordAgentTurnSessionSummary,
|
|
159
161
|
recordAuthorizationCompleted
|
|
160
|
-
} from "./chunk-
|
|
162
|
+
} from "./chunk-OQQU3SD6.js";
|
|
161
163
|
import {
|
|
162
164
|
SlackActionError,
|
|
163
165
|
bindSlackDirectCredentialSubject,
|
|
@@ -176,7 +178,7 @@ import {
|
|
|
176
178
|
setPlugins,
|
|
177
179
|
validatePlugins,
|
|
178
180
|
verifySlackDirectCredentialSubject
|
|
179
|
-
} from "./chunk-
|
|
181
|
+
} from "./chunk-7K3JALTQ.js";
|
|
180
182
|
import {
|
|
181
183
|
createPluginLogger,
|
|
182
184
|
createPluginState
|
|
@@ -5333,6 +5335,23 @@ async function GET4(request, provider, waitUntil, options) {
|
|
|
5333
5335
|
}
|
|
5334
5336
|
} catch (error) {
|
|
5335
5337
|
if (error instanceof ResumeTurnBusyError) {
|
|
5338
|
+
logWarn(
|
|
5339
|
+
"oauth_callback_resume_busy",
|
|
5340
|
+
{
|
|
5341
|
+
...stored.resumeConversationId && {
|
|
5342
|
+
conversationId: stored.resumeConversationId
|
|
5343
|
+
},
|
|
5344
|
+
...stored.userId && { actorId: stored.userId },
|
|
5345
|
+
...stored.channelId && { channelId: stored.channelId }
|
|
5346
|
+
},
|
|
5347
|
+
{
|
|
5348
|
+
"app.credential.provider": stored.provider,
|
|
5349
|
+
...stored.resumeSessionId && {
|
|
5350
|
+
"app.ai.session_id": stored.resumeSessionId
|
|
5351
|
+
}
|
|
5352
|
+
},
|
|
5353
|
+
"OAuth callback resume was busy; user must send another message to continue"
|
|
5354
|
+
);
|
|
5336
5355
|
return;
|
|
5337
5356
|
}
|
|
5338
5357
|
throw error;
|
|
@@ -5936,6 +5955,16 @@ async function handleSlashCommand(event) {
|
|
|
5936
5955
|
}
|
|
5937
5956
|
}
|
|
5938
5957
|
|
|
5958
|
+
// src/chat/credentials/unlink-provider.ts
|
|
5959
|
+
async function unlinkProvider(userId, provider, userTokenStore) {
|
|
5960
|
+
await Promise.all([
|
|
5961
|
+
userTokenStore.delete(userId, provider),
|
|
5962
|
+
deleteMcpStoredOAuthCredentials(userId, provider),
|
|
5963
|
+
deleteMcpServerSessionId(userId, provider),
|
|
5964
|
+
deleteMcpAuthSessionsForUserProvider(userId, provider)
|
|
5965
|
+
]);
|
|
5966
|
+
}
|
|
5967
|
+
|
|
5939
5968
|
// src/chat/ingress/slack-webhook.ts
|
|
5940
5969
|
var IGNORED_MESSAGE_SUBTYPES = /* @__PURE__ */ new Set([
|
|
5941
5970
|
"message_changed",
|
|
@@ -30,6 +30,8 @@ interface ToolWiringArgs {
|
|
|
30
30
|
abortAgent: () => void;
|
|
31
31
|
activeSkills: Skill[];
|
|
32
32
|
currentActor?: Actor;
|
|
33
|
+
/** Live projection of the run's committed instruction-authority actors so far. */
|
|
34
|
+
currentActors?: () => Actor[];
|
|
33
35
|
artifactStatePatch: Partial<ThreadArtifactsState>;
|
|
34
36
|
availableSkills: SkillMetadata[];
|
|
35
37
|
configurationValues: Record<string, unknown>;
|
|
@@ -52,4 +52,6 @@ export declare function getPluginOperationalReports(nowMs: number, conversations
|
|
|
52
52
|
/** Create one runner over runtime hook plugins registered by the app. */
|
|
53
53
|
export declare function createPluginHookRunner(input?: {
|
|
54
54
|
actor?: Actor;
|
|
55
|
+
/** Live getter for the run's committed instruction actors; see `multi-actor-runs.md`. */
|
|
56
|
+
actors?: () => Actor[];
|
|
55
57
|
}): PluginHookRunner;
|
|
@@ -11,7 +11,7 @@ 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
17
|
} from "./chunk-PFXC67GJ.js";
|
|
@@ -33,15 +33,17 @@ import {
|
|
|
33
33
|
formatSlackLink,
|
|
34
34
|
isNoReplyMarker,
|
|
35
35
|
stripNoReplyMarker
|
|
36
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-IWKVXO3F.js";
|
|
37
37
|
import {
|
|
38
|
+
instructionActors,
|
|
39
|
+
instructionProvenanceFor,
|
|
38
40
|
loadConnectedMcpProviders,
|
|
39
41
|
recordAuthorizationRequested,
|
|
40
42
|
recordMcpProviderConnected,
|
|
41
43
|
recordSubagentEnded,
|
|
42
44
|
recordSubagentStarted,
|
|
43
45
|
recordToolExecutionStarted
|
|
44
|
-
} from "./chunk-
|
|
46
|
+
} from "./chunk-OQQU3SD6.js";
|
|
45
47
|
import {
|
|
46
48
|
SlackActionError,
|
|
47
49
|
createPluginHookRunner,
|
|
@@ -58,7 +60,7 @@ import {
|
|
|
58
60
|
normalizeSlackConversationId,
|
|
59
61
|
resolveChannelCapabilities,
|
|
60
62
|
withSlackRetries
|
|
61
|
-
} from "./chunk-
|
|
63
|
+
} from "./chunk-7K3JALTQ.js";
|
|
62
64
|
import {
|
|
63
65
|
createPluginLogger
|
|
64
66
|
} from "./chunk-OZJXGX4U.js";
|
|
@@ -8668,280 +8670,10 @@ import { PluginToolInputError } from "@sentry/junior-plugin-api";
|
|
|
8668
8670
|
// src/chat/services/plugin-auth-orchestration.ts
|
|
8669
8671
|
import { THREAD_STATE_TTL_MS as THREAD_STATE_TTL_MS2 } from "chat";
|
|
8670
8672
|
|
|
8671
|
-
// src/chat/mcp/auth-store.ts
|
|
8672
|
-
import {
|
|
8673
|
-
sourceSchema
|
|
8674
|
-
} from "@sentry/junior-plugin-api";
|
|
8675
|
-
var MCP_AUTH_SESSION_PREFIX = "junior:mcp_auth_session";
|
|
8676
|
-
var MCP_AUTH_CREDENTIALS_PREFIX = "junior:mcp_auth_credentials";
|
|
8677
|
-
var MCP_AUTH_SESSION_INDEX_PREFIX = "junior:mcp_auth_session_index";
|
|
8678
|
-
var MCP_SERVER_SESSION_PREFIX = "junior:mcp_server_session";
|
|
8679
|
-
var MCP_AUTH_SESSION_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
8680
|
-
var MCP_AUTH_CREDENTIALS_TTL_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
8681
|
-
var MCP_SERVER_SESSION_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
8682
|
-
function sessionKey(authSessionId) {
|
|
8683
|
-
return `${MCP_AUTH_SESSION_PREFIX}:${authSessionId}`;
|
|
8684
|
-
}
|
|
8685
|
-
function credentialsKey(userId, provider) {
|
|
8686
|
-
return `${MCP_AUTH_CREDENTIALS_PREFIX}:${userId}:${provider}`;
|
|
8687
|
-
}
|
|
8688
|
-
function sessionIndexKey(userId, provider) {
|
|
8689
|
-
return `${MCP_AUTH_SESSION_INDEX_PREFIX}:${userId}:${provider}`;
|
|
8690
|
-
}
|
|
8691
|
-
function serverSessionKey(userId, provider) {
|
|
8692
|
-
return `${MCP_SERVER_SESSION_PREFIX}:${userId}:${provider}`;
|
|
8693
|
-
}
|
|
8694
|
-
function parseSessionIndex(value) {
|
|
8695
|
-
if (typeof value !== "string") {
|
|
8696
|
-
return [];
|
|
8697
|
-
}
|
|
8698
|
-
try {
|
|
8699
|
-
const parsed = JSON.parse(value);
|
|
8700
|
-
if (!Array.isArray(parsed)) {
|
|
8701
|
-
return [];
|
|
8702
|
-
}
|
|
8703
|
-
return [
|
|
8704
|
-
...new Set(parsed.filter((id) => typeof id === "string"))
|
|
8705
|
-
];
|
|
8706
|
-
} catch {
|
|
8707
|
-
return [];
|
|
8708
|
-
}
|
|
8709
|
-
}
|
|
8710
|
-
function parseMcpAuthSession(value) {
|
|
8711
|
-
if (typeof value !== "string") {
|
|
8712
|
-
return void 0;
|
|
8713
|
-
}
|
|
8714
|
-
try {
|
|
8715
|
-
const parsed = JSON.parse(value);
|
|
8716
|
-
if (!isRecord(parsed)) {
|
|
8717
|
-
return void 0;
|
|
8718
|
-
}
|
|
8719
|
-
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") {
|
|
8720
|
-
return void 0;
|
|
8721
|
-
}
|
|
8722
|
-
const destination = parsed.destination === void 0 ? void 0 : parseDestination(parsed.destination);
|
|
8723
|
-
if (parsed.destination !== void 0 && !destination) {
|
|
8724
|
-
return void 0;
|
|
8725
|
-
}
|
|
8726
|
-
const source = parsed.source === void 0 ? void 0 : sourceSchema.safeParse(parsed.source);
|
|
8727
|
-
if (parsed.source !== void 0 && (!source || !source.success)) {
|
|
8728
|
-
return void 0;
|
|
8729
|
-
}
|
|
8730
|
-
return {
|
|
8731
|
-
authSessionId: parsed.authSessionId,
|
|
8732
|
-
provider: parsed.provider,
|
|
8733
|
-
userId: parsed.userId,
|
|
8734
|
-
conversationId: parsed.conversationId,
|
|
8735
|
-
...destination ? { destination } : {},
|
|
8736
|
-
...source?.success ? { source: source.data } : {},
|
|
8737
|
-
sessionId: parsed.sessionId,
|
|
8738
|
-
userMessage: parsed.userMessage,
|
|
8739
|
-
createdAtMs: parsed.createdAtMs,
|
|
8740
|
-
updatedAtMs: parsed.updatedAtMs,
|
|
8741
|
-
...typeof parsed.channelId === "string" ? { channelId: parsed.channelId } : {},
|
|
8742
|
-
...typeof parsed.threadTs === "string" ? { threadTs: parsed.threadTs } : {},
|
|
8743
|
-
...typeof parsed.toolChannelId === "string" ? { toolChannelId: parsed.toolChannelId } : {},
|
|
8744
|
-
...isRecord(parsed.configuration) ? { configuration: parsed.configuration } : {},
|
|
8745
|
-
...isRecord(parsed.artifactState) ? { artifactState: parsed.artifactState } : {},
|
|
8746
|
-
...typeof parsed.authorizationUrl === "string" ? { authorizationUrl: parsed.authorizationUrl } : {},
|
|
8747
|
-
...typeof parsed.codeVerifier === "string" ? { codeVerifier: parsed.codeVerifier } : {}
|
|
8748
|
-
};
|
|
8749
|
-
} catch {
|
|
8750
|
-
return void 0;
|
|
8751
|
-
}
|
|
8752
|
-
}
|
|
8753
|
-
function parseServerSession(value) {
|
|
8754
|
-
if (typeof value !== "string") {
|
|
8755
|
-
return void 0;
|
|
8756
|
-
}
|
|
8757
|
-
try {
|
|
8758
|
-
const parsed = JSON.parse(value);
|
|
8759
|
-
if (!isRecord(parsed) || typeof parsed.sessionId !== "string" || typeof parsed.updatedAtMs !== "number") {
|
|
8760
|
-
return void 0;
|
|
8761
|
-
}
|
|
8762
|
-
return {
|
|
8763
|
-
sessionId: parsed.sessionId,
|
|
8764
|
-
updatedAtMs: parsed.updatedAtMs
|
|
8765
|
-
};
|
|
8766
|
-
} catch {
|
|
8767
|
-
return void 0;
|
|
8768
|
-
}
|
|
8769
|
-
}
|
|
8770
|
-
function parseStoredCredentials(value) {
|
|
8771
|
-
if (typeof value !== "string") {
|
|
8772
|
-
return void 0;
|
|
8773
|
-
}
|
|
8774
|
-
try {
|
|
8775
|
-
const parsed = JSON.parse(value);
|
|
8776
|
-
if (!isRecord(parsed)) {
|
|
8777
|
-
return void 0;
|
|
8778
|
-
}
|
|
8779
|
-
return {
|
|
8780
|
-
...isRecord(parsed.clientInformation) ? {
|
|
8781
|
-
clientInformation: parsed.clientInformation
|
|
8782
|
-
} : {},
|
|
8783
|
-
...isRecord(parsed.discoveryState) ? {
|
|
8784
|
-
discoveryState: parsed.discoveryState
|
|
8785
|
-
} : {},
|
|
8786
|
-
...isRecord(parsed.tokens) ? { tokens: parsed.tokens } : {}
|
|
8787
|
-
};
|
|
8788
|
-
} catch {
|
|
8789
|
-
return void 0;
|
|
8790
|
-
}
|
|
8791
|
-
}
|
|
8792
|
-
async function getConnectedStateAdapter() {
|
|
8793
|
-
const stateAdapter = getStateAdapter();
|
|
8794
|
-
await stateAdapter.connect();
|
|
8795
|
-
return stateAdapter;
|
|
8796
|
-
}
|
|
8797
|
-
async function getMcpAuthSession(authSessionId) {
|
|
8798
|
-
const stateAdapter = await getConnectedStateAdapter();
|
|
8799
|
-
return parseMcpAuthSession(await stateAdapter.get(sessionKey(authSessionId)));
|
|
8800
|
-
}
|
|
8801
|
-
async function putMcpAuthSession(session, ttlMs2 = MCP_AUTH_SESSION_TTL_MS) {
|
|
8802
|
-
const stateAdapter = await getConnectedStateAdapter();
|
|
8803
|
-
await stateAdapter.set(
|
|
8804
|
-
sessionKey(session.authSessionId),
|
|
8805
|
-
JSON.stringify(session),
|
|
8806
|
-
ttlMs2
|
|
8807
|
-
);
|
|
8808
|
-
const nextIndex = parseSessionIndex(
|
|
8809
|
-
await stateAdapter.get(sessionIndexKey(session.userId, session.provider))
|
|
8810
|
-
);
|
|
8811
|
-
if (!nextIndex.includes(session.authSessionId)) {
|
|
8812
|
-
nextIndex.push(session.authSessionId);
|
|
8813
|
-
}
|
|
8814
|
-
await stateAdapter.set(
|
|
8815
|
-
sessionIndexKey(session.userId, session.provider),
|
|
8816
|
-
JSON.stringify(nextIndex),
|
|
8817
|
-
ttlMs2
|
|
8818
|
-
);
|
|
8819
|
-
}
|
|
8820
|
-
async function patchMcpAuthSession(authSessionId, patch) {
|
|
8821
|
-
const current = await getMcpAuthSession(authSessionId);
|
|
8822
|
-
if (!current) {
|
|
8823
|
-
throw new Error(`Unknown MCP auth session: ${authSessionId}`);
|
|
8824
|
-
}
|
|
8825
|
-
const next = {
|
|
8826
|
-
...current,
|
|
8827
|
-
...patch,
|
|
8828
|
-
authSessionId: current.authSessionId,
|
|
8829
|
-
provider: current.provider,
|
|
8830
|
-
userId: current.userId,
|
|
8831
|
-
conversationId: current.conversationId,
|
|
8832
|
-
...current.destination ? { destination: current.destination } : {},
|
|
8833
|
-
sessionId: current.sessionId,
|
|
8834
|
-
userMessage: current.userMessage,
|
|
8835
|
-
createdAtMs: current.createdAtMs,
|
|
8836
|
-
updatedAtMs: Date.now()
|
|
8837
|
-
};
|
|
8838
|
-
await putMcpAuthSession(next);
|
|
8839
|
-
return next;
|
|
8840
|
-
}
|
|
8841
|
-
async function deleteMcpAuthSession(authSessionId) {
|
|
8842
|
-
const stateAdapter = await getConnectedStateAdapter();
|
|
8843
|
-
const current = parseMcpAuthSession(
|
|
8844
|
-
await stateAdapter.get(sessionKey(authSessionId))
|
|
8845
|
-
);
|
|
8846
|
-
await stateAdapter.delete(sessionKey(authSessionId));
|
|
8847
|
-
if (!current) {
|
|
8848
|
-
return;
|
|
8849
|
-
}
|
|
8850
|
-
const nextIndex = parseSessionIndex(
|
|
8851
|
-
await stateAdapter.get(sessionIndexKey(current.userId, current.provider))
|
|
8852
|
-
).filter((id) => id !== authSessionId);
|
|
8853
|
-
if (nextIndex.length > 0) {
|
|
8854
|
-
await stateAdapter.set(
|
|
8855
|
-
sessionIndexKey(current.userId, current.provider),
|
|
8856
|
-
JSON.stringify(nextIndex),
|
|
8857
|
-
MCP_AUTH_SESSION_TTL_MS
|
|
8858
|
-
);
|
|
8859
|
-
return;
|
|
8860
|
-
}
|
|
8861
|
-
await stateAdapter.delete(sessionIndexKey(current.userId, current.provider));
|
|
8862
|
-
}
|
|
8863
|
-
async function deleteMcpAuthSessionsForUserProvider(userId, provider) {
|
|
8864
|
-
const stateAdapter = await getConnectedStateAdapter();
|
|
8865
|
-
const indexKey = sessionIndexKey(userId, provider);
|
|
8866
|
-
const authSessionIds = parseSessionIndex(await stateAdapter.get(indexKey));
|
|
8867
|
-
for (const authSessionId of authSessionIds) {
|
|
8868
|
-
await stateAdapter.delete(sessionKey(authSessionId));
|
|
8869
|
-
}
|
|
8870
|
-
await stateAdapter.delete(indexKey);
|
|
8871
|
-
}
|
|
8872
|
-
async function getLatestMcpAuthSessionForUserProvider(userId, provider) {
|
|
8873
|
-
const stateAdapter = await getConnectedStateAdapter();
|
|
8874
|
-
const authSessionIds = parseSessionIndex(
|
|
8875
|
-
await stateAdapter.get(sessionIndexKey(userId, provider))
|
|
8876
|
-
);
|
|
8877
|
-
let latestSession;
|
|
8878
|
-
for (const authSessionId of authSessionIds) {
|
|
8879
|
-
const session = parseMcpAuthSession(
|
|
8880
|
-
await stateAdapter.get(sessionKey(authSessionId))
|
|
8881
|
-
);
|
|
8882
|
-
if (!session) {
|
|
8883
|
-
continue;
|
|
8884
|
-
}
|
|
8885
|
-
if (!latestSession || session.updatedAtMs > latestSession.updatedAtMs) {
|
|
8886
|
-
latestSession = session;
|
|
8887
|
-
}
|
|
8888
|
-
}
|
|
8889
|
-
return latestSession;
|
|
8890
|
-
}
|
|
8891
|
-
async function getMcpStoredOAuthCredentials(userId, provider) {
|
|
8892
|
-
const stateAdapter = await getConnectedStateAdapter();
|
|
8893
|
-
return parseStoredCredentials(
|
|
8894
|
-
await stateAdapter.get(credentialsKey(userId, provider))
|
|
8895
|
-
);
|
|
8896
|
-
}
|
|
8897
|
-
async function putMcpStoredOAuthCredentials(userId, provider, value, ttlMs2 = MCP_AUTH_CREDENTIALS_TTL_MS) {
|
|
8898
|
-
const stateAdapter = await getConnectedStateAdapter();
|
|
8899
|
-
await stateAdapter.set(
|
|
8900
|
-
credentialsKey(userId, provider),
|
|
8901
|
-
JSON.stringify(value),
|
|
8902
|
-
ttlMs2
|
|
8903
|
-
);
|
|
8904
|
-
}
|
|
8905
|
-
async function deleteMcpStoredOAuthCredentials(userId, provider) {
|
|
8906
|
-
const stateAdapter = await getConnectedStateAdapter();
|
|
8907
|
-
await stateAdapter.delete(credentialsKey(userId, provider));
|
|
8908
|
-
}
|
|
8909
|
-
async function getMcpServerSessionId(userId, provider) {
|
|
8910
|
-
const stateAdapter = await getConnectedStateAdapter();
|
|
8911
|
-
return parseServerSession(
|
|
8912
|
-
await stateAdapter.get(serverSessionKey(userId, provider))
|
|
8913
|
-
)?.sessionId;
|
|
8914
|
-
}
|
|
8915
|
-
async function putMcpServerSessionId(userId, provider, sessionId, ttlMs2 = MCP_SERVER_SESSION_TTL_MS) {
|
|
8916
|
-
const stateAdapter = await getConnectedStateAdapter();
|
|
8917
|
-
await stateAdapter.set(
|
|
8918
|
-
serverSessionKey(userId, provider),
|
|
8919
|
-
JSON.stringify({
|
|
8920
|
-
sessionId,
|
|
8921
|
-
updatedAtMs: Date.now()
|
|
8922
|
-
}),
|
|
8923
|
-
ttlMs2
|
|
8924
|
-
);
|
|
8925
|
-
}
|
|
8926
|
-
async function deleteMcpServerSessionId(userId, provider) {
|
|
8927
|
-
const stateAdapter = await getConnectedStateAdapter();
|
|
8928
|
-
await stateAdapter.delete(serverSessionKey(userId, provider));
|
|
8929
|
-
}
|
|
8930
|
-
|
|
8931
|
-
// src/chat/credentials/unlink-provider.ts
|
|
8932
|
-
async function unlinkProvider(userId, provider, userTokenStore) {
|
|
8933
|
-
await Promise.all([
|
|
8934
|
-
userTokenStore.delete(userId, provider),
|
|
8935
|
-
deleteMcpStoredOAuthCredentials(userId, provider),
|
|
8936
|
-
deleteMcpServerSessionId(userId, provider),
|
|
8937
|
-
deleteMcpAuthSessionsForUserProvider(userId, provider)
|
|
8938
|
-
]);
|
|
8939
|
-
}
|
|
8940
|
-
|
|
8941
8673
|
// src/chat/oauth-flow.ts
|
|
8942
8674
|
import { randomBytes } from "crypto";
|
|
8943
8675
|
import {
|
|
8944
|
-
sourceSchema
|
|
8676
|
+
sourceSchema
|
|
8945
8677
|
} from "@sentry/junior-plugin-api";
|
|
8946
8678
|
|
|
8947
8679
|
// src/chat/oauth-authorization-message.ts
|
|
@@ -8965,7 +8697,7 @@ function parseOAuthStatePayload(value) {
|
|
|
8965
8697
|
if (value.destination !== void 0 && !destination) {
|
|
8966
8698
|
return void 0;
|
|
8967
8699
|
}
|
|
8968
|
-
const source = value.source === void 0 ? void 0 :
|
|
8700
|
+
const source = value.source === void 0 ? void 0 : sourceSchema.safeParse(value.source);
|
|
8969
8701
|
if (value.source !== void 0 && (!source || !source.success)) {
|
|
8970
8702
|
return void 0;
|
|
8971
8703
|
}
|
|
@@ -9306,9 +9038,6 @@ function createPluginAuthOrchestration(input) {
|
|
|
9306
9038
|
);
|
|
9307
9039
|
}
|
|
9308
9040
|
}
|
|
9309
|
-
if (options?.unlinkExistingProvider && input.actorId && input.userTokenStore) {
|
|
9310
|
-
await unlinkProvider(input.actorId, provider, input.userTokenStore);
|
|
9311
|
-
}
|
|
9312
9041
|
if (input.sessionId && recordPendingAuth) {
|
|
9313
9042
|
await recordPendingAuth({
|
|
9314
9043
|
kind: "plugin",
|
|
@@ -9376,10 +9105,10 @@ function createPluginAuthOrchestration(input) {
|
|
|
9376
9105
|
signal.message ?? `${formatProviderLabel(provider)} credentials are required but the provider is not configured for OAuth.`
|
|
9377
9106
|
);
|
|
9378
9107
|
}
|
|
9379
|
-
await startAuthorizationPause(
|
|
9380
|
-
|
|
9381
|
-
|
|
9382
|
-
|
|
9108
|
+
await startAuthorizationPause(
|
|
9109
|
+
authorization.provider,
|
|
9110
|
+
authorization.scope ? { scope: authorization.scope } : void 0
|
|
9111
|
+
);
|
|
9383
9112
|
},
|
|
9384
9113
|
getPendingPause: () => pendingPause
|
|
9385
9114
|
};
|
|
@@ -11704,132 +11433,392 @@ function createSandboxExecutor(options) {
|
|
|
11704
11433
|
);
|
|
11705
11434
|
return { result };
|
|
11706
11435
|
};
|
|
11707
|
-
const executeFindFilesTool = async (rawInput) => {
|
|
11708
|
-
const pattern = String(rawInput.pattern ?? "");
|
|
11709
|
-
if (!pattern) {
|
|
11710
|
-
throw new ToolInputError("pattern is required");
|
|
11711
|
-
}
|
|
11712
|
-
logSandboxBootRequest("tool.findFiles");
|
|
11713
|
-
const limit = positiveInteger(rawInput.limit);
|
|
11714
|
-
const executors = await sessionManager.ensureToolExecutors();
|
|
11715
|
-
const result = await withSandboxToolSpan(
|
|
11716
|
-
"sandbox.findFiles",
|
|
11717
|
-
"sandbox.fs.find",
|
|
11718
|
-
{
|
|
11719
|
-
"app.sandbox.pattern.length": pattern.length
|
|
11720
|
-
},
|
|
11721
|
-
async () => {
|
|
11722
|
-
const response = await findFiles({
|
|
11723
|
-
fs: executors.fs,
|
|
11724
|
-
pattern,
|
|
11725
|
-
...typeof rawInput.path === "string" ? { path: rawInput.path } : {},
|
|
11726
|
-
...limit ? { limit } : {}
|
|
11727
|
-
});
|
|
11728
|
-
setSpanStatus("ok");
|
|
11729
|
-
return response;
|
|
11730
|
-
}
|
|
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
|
|
11731
11750
|
);
|
|
11732
|
-
return
|
|
11733
|
-
}
|
|
11734
|
-
|
|
11735
|
-
|
|
11736
|
-
|
|
11737
|
-
|
|
11738
|
-
|
|
11739
|
-
|
|
11740
|
-
|
|
11741
|
-
|
|
11742
|
-
|
|
11743
|
-
|
|
11744
|
-
|
|
11745
|
-
|
|
11746
|
-
|
|
11747
|
-
|
|
11748
|
-
|
|
11749
|
-
|
|
11750
|
-
|
|
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))
|
|
11751
11773
|
);
|
|
11752
|
-
|
|
11753
|
-
|
|
11754
|
-
const execute = async (params) => {
|
|
11755
|
-
const rawInput = params.input ?? {};
|
|
11756
|
-
const bashCommand = params.toolName === "bash" ? String(rawInput.command ?? "").trim() : void 0;
|
|
11757
|
-
if (params.toolName === "bash") {
|
|
11758
|
-
if (!bashCommand) {
|
|
11759
|
-
throw new ToolInputError("command is required");
|
|
11760
|
-
}
|
|
11761
|
-
if (options?.runBashCustomCommand) {
|
|
11762
|
-
const custom = await options.runBashCustomCommand(bashCommand);
|
|
11763
|
-
if (custom.handled) {
|
|
11764
|
-
if (!custom.result) {
|
|
11765
|
-
throw new Error("Custom bash command handler returned no result.");
|
|
11766
|
-
}
|
|
11767
|
-
return { result: bashToolResult(custom.result) };
|
|
11768
|
-
}
|
|
11769
|
-
}
|
|
11770
|
-
return await executeBashTool(rawInput, bashCommand, params.signal);
|
|
11771
|
-
}
|
|
11772
|
-
try {
|
|
11773
|
-
if (params.toolName === "readFile") {
|
|
11774
|
-
return await executeReadFileTool(rawInput);
|
|
11775
|
-
}
|
|
11776
|
-
if (params.toolName === "editFile") {
|
|
11777
|
-
return await executeEditFileTool(rawInput);
|
|
11778
|
-
}
|
|
11779
|
-
if (params.toolName === "grep") {
|
|
11780
|
-
return await executeGrepTool(rawInput);
|
|
11781
|
-
}
|
|
11782
|
-
if (params.toolName === "findFiles") {
|
|
11783
|
-
return await executeFindFilesTool(rawInput);
|
|
11784
|
-
}
|
|
11785
|
-
if (params.toolName === "listDir") {
|
|
11786
|
-
return await executeListDirTool(rawInput);
|
|
11787
|
-
}
|
|
11788
|
-
if (params.toolName === "writeFile") {
|
|
11789
|
-
return await executeWriteFileTool(rawInput);
|
|
11790
|
-
}
|
|
11791
|
-
} catch (error) {
|
|
11792
|
-
if (!isSandboxCommandStreamInterruptedError(error)) {
|
|
11793
|
-
throw error;
|
|
11794
|
-
}
|
|
11795
|
-
return { result: sandboxStreamInterruptedResult(params.toolName) };
|
|
11774
|
+
if (!session) {
|
|
11775
|
+
continue;
|
|
11796
11776
|
}
|
|
11797
|
-
|
|
11798
|
-
|
|
11799
|
-
return {
|
|
11800
|
-
configureSkills(skills) {
|
|
11801
|
-
availableSkills = [...skills];
|
|
11802
|
-
sessionManager.configureSkills(skills);
|
|
11803
|
-
},
|
|
11804
|
-
configureReferenceFiles(files) {
|
|
11805
|
-
referenceFiles = [...files];
|
|
11806
|
-
sessionManager.configureReferenceFiles(files);
|
|
11807
|
-
},
|
|
11808
|
-
getSandboxId() {
|
|
11809
|
-
return sessionManager.getSandboxId();
|
|
11810
|
-
},
|
|
11811
|
-
getDependencyProfileHash() {
|
|
11812
|
-
return sessionManager.getDependencyProfileHash();
|
|
11813
|
-
},
|
|
11814
|
-
canExecute(toolName) {
|
|
11815
|
-
return SANDBOX_TOOL_NAMES.has(toolName);
|
|
11816
|
-
},
|
|
11817
|
-
async createSandbox() {
|
|
11818
|
-
return await sessionManager.createSandbox();
|
|
11819
|
-
},
|
|
11820
|
-
execute,
|
|
11821
|
-
async dispose() {
|
|
11822
|
-
await sessionManager.dispose();
|
|
11777
|
+
if (!latestSession || session.updatedAtMs > latestSession.updatedAtMs) {
|
|
11778
|
+
latestSession = session;
|
|
11823
11779
|
}
|
|
11824
|
-
}
|
|
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));
|
|
11825
11821
|
}
|
|
11826
|
-
|
|
11827
|
-
// src/chat/services/mcp-auth-orchestration.ts
|
|
11828
|
-
import { THREAD_STATE_TTL_MS as THREAD_STATE_TTL_MS3 } from "chat";
|
|
11829
|
-
|
|
11830
|
-
// src/chat/mcp/oauth.ts
|
|
11831
|
-
import { randomUUID as randomUUID3 } from "crypto";
|
|
11832
|
-
import { StreamableHTTPClientTransport as StreamableHTTPClientTransport2 } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
11833
11822
|
|
|
11834
11823
|
// src/chat/mcp/oauth-provider.ts
|
|
11835
11824
|
function createClientMetadata(callbackUrl) {
|
|
@@ -13358,7 +13347,8 @@ async function wireAgentTools(args) {
|
|
|
13358
13347
|
const authActorId = args.routing.credentialContext && "type" in args.routing.credentialContext.actor ? args.routing.credentialContext.actor.userId : void 0;
|
|
13359
13348
|
const userTokenStore = createUserTokenStore();
|
|
13360
13349
|
const pluginHooks = createPluginHookRunner({
|
|
13361
|
-
actor: args.currentActor
|
|
13350
|
+
actor: args.currentActor,
|
|
13351
|
+
actors: args.currentActors
|
|
13362
13352
|
});
|
|
13363
13353
|
const sandboxExecutor = createSandboxExecutor({
|
|
13364
13354
|
sandboxId: args.state.sandbox?.sandboxId,
|
|
@@ -14002,6 +13992,11 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy) {
|
|
|
14002
13992
|
currentSliceId,
|
|
14003
13993
|
existingSessionRecord
|
|
14004
13994
|
} = await restoreSessionRecord(routing);
|
|
13995
|
+
const committedInstructionProvenance = existingSessionRecord?.piMessageProvenance ? [
|
|
13996
|
+
...existingSessionRecord.piMessageProvenance,
|
|
13997
|
+
...resumedFromSessionRecord ? [] : [instructionProvenanceFor(actor)]
|
|
13998
|
+
] : [instructionProvenanceFor(actor)];
|
|
13999
|
+
const runActors = () => instructionActors(committedInstructionProvenance);
|
|
14005
14000
|
canRecordMcpProviders = Boolean(
|
|
14006
14001
|
sessionRecordState.canUseTurnSession && sessionConversationId && sessionId
|
|
14007
14002
|
);
|
|
@@ -14107,6 +14102,7 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy) {
|
|
|
14107
14102
|
abortAgent: () => agent?.abort(),
|
|
14108
14103
|
activeSkills,
|
|
14109
14104
|
currentActor: actor,
|
|
14105
|
+
currentActors: runActors,
|
|
14110
14106
|
artifactStatePatch,
|
|
14111
14107
|
availableSkills,
|
|
14112
14108
|
configurationValues,
|
|
@@ -14181,6 +14177,9 @@ async function executeAgentRunInPrivacyContext(request, conversationPrivacy) {
|
|
|
14181
14177
|
[...agent.state.messages, ...piMessages],
|
|
14182
14178
|
messages.map((message) => message.provenance)
|
|
14183
14179
|
);
|
|
14180
|
+
committedInstructionProvenance.push(
|
|
14181
|
+
...messages.map((message) => message.provenance)
|
|
14182
|
+
);
|
|
14184
14183
|
for (const message of piMessages) {
|
|
14185
14184
|
agent.steer(message);
|
|
14186
14185
|
}
|
|
@@ -14583,9 +14582,6 @@ export {
|
|
|
14583
14582
|
removeReactionFromMessage,
|
|
14584
14583
|
renderSlackLegacyAttachmentText,
|
|
14585
14584
|
appendSlackLegacyAttachmentText,
|
|
14586
|
-
deleteMcpAuthSession,
|
|
14587
|
-
getMcpStoredOAuthCredentials,
|
|
14588
|
-
unlinkProvider,
|
|
14589
14585
|
parseOAuthStatePayload,
|
|
14590
14586
|
formatProviderLabel,
|
|
14591
14587
|
resolveBaseUrl,
|
|
@@ -14596,6 +14592,11 @@ export {
|
|
|
14596
14592
|
normalizeSandboxEgressTracePropagationDomains,
|
|
14597
14593
|
shouldPropagateSandboxEgressTrace,
|
|
14598
14594
|
resolveSandboxEgressProviderForHost,
|
|
14595
|
+
deleteMcpAuthSession,
|
|
14596
|
+
deleteMcpAuthSessionsForUserProvider,
|
|
14597
|
+
getMcpStoredOAuthCredentials,
|
|
14598
|
+
deleteMcpStoredOAuthCredentials,
|
|
14599
|
+
deleteMcpServerSessionId,
|
|
14599
14600
|
finalizeMcpAuthorization,
|
|
14600
14601
|
resolvePluginOAuthAccount,
|
|
14601
14602
|
executeCredentialedEgressRequest,
|
|
@@ -1367,6 +1367,7 @@ function createPluginHookRunner(input = {}) {
|
|
|
1367
1367
|
async beforeToolExecute(tool) {
|
|
1368
1368
|
let nextInput = { ...tool.input };
|
|
1369
1369
|
const env = normalizeEnv(nextInput.env);
|
|
1370
|
+
const actors = input.actors?.() ?? (input.actor ? [input.actor] : []);
|
|
1370
1371
|
for (const plugin of loaded) {
|
|
1371
1372
|
const pluginName = plugin.manifest.name;
|
|
1372
1373
|
const hook = plugin.hooks?.beforeToolExecute;
|
|
@@ -1378,6 +1379,7 @@ function createPluginHookRunner(input = {}) {
|
|
|
1378
1379
|
await hook({
|
|
1379
1380
|
...basePluginContext(plugin),
|
|
1380
1381
|
actor: input.actor,
|
|
1382
|
+
actors,
|
|
1381
1383
|
tool: {
|
|
1382
1384
|
name: tool.name,
|
|
1383
1385
|
input: nextInput
|
|
@@ -8,19 +8,19 @@ import {
|
|
|
8
8
|
getPersistedThreadState,
|
|
9
9
|
markTurnCompleted,
|
|
10
10
|
mergeArtifactsState
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-Z4FOYQXW.js";
|
|
12
12
|
import {
|
|
13
13
|
coerceThreadConversationState
|
|
14
14
|
} from "./chunk-PFXC67GJ.js";
|
|
15
15
|
import {
|
|
16
16
|
getAgentTurnSessionRecord,
|
|
17
17
|
getInterruptionMarker
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-OQQU3SD6.js";
|
|
19
19
|
import {
|
|
20
20
|
createPluginEmbedder,
|
|
21
21
|
createPluginModel,
|
|
22
22
|
getPlugins
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-7K3JALTQ.js";
|
|
24
24
|
import {
|
|
25
25
|
createPluginLogger,
|
|
26
26
|
createPluginState
|
package/dist/cli/chat.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createAgentRunner,
|
|
3
3
|
executeAgentRun
|
|
4
|
-
} from "../chunk-
|
|
5
|
-
import "../chunk-
|
|
4
|
+
} from "../chunk-56SIBIVF.js";
|
|
5
|
+
import "../chunk-Z4FOYQXW.js";
|
|
6
6
|
import "../chunk-PFXC67GJ.js";
|
|
7
7
|
import "../chunk-H7KUZAMZ.js";
|
|
8
|
-
import "../chunk-
|
|
9
|
-
import "../chunk-
|
|
8
|
+
import "../chunk-IWKVXO3F.js";
|
|
9
|
+
import "../chunk-OQQU3SD6.js";
|
|
10
10
|
import {
|
|
11
11
|
loadAppPluginSet
|
|
12
12
|
} from "../chunk-Y2CM7HXH.js";
|
|
13
|
-
import "../chunk-
|
|
13
|
+
import "../chunk-7K3JALTQ.js";
|
|
14
14
|
import "../chunk-OZJXGX4U.js";
|
|
15
15
|
import "../chunk-G3E7SCME.js";
|
|
16
16
|
import "../chunk-ZATRYQLR.js";
|
|
@@ -147,7 +147,7 @@ async function configureLocalChatPlugins(pluginSet) {
|
|
|
147
147
|
databaseModule
|
|
148
148
|
] = await Promise.all([
|
|
149
149
|
import("../plugins-PZMDS7AT.js"),
|
|
150
|
-
import("../agent-hooks-
|
|
150
|
+
import("../agent-hooks-KL7I3ZRC.js"),
|
|
151
151
|
import("../catalog-runtime-NZHMSMYC.js"),
|
|
152
152
|
import("../validation-KYAWETI4.js"),
|
|
153
153
|
import("../db-GCK43OO3.js")
|
|
@@ -211,7 +211,7 @@ function newRunConversationId() {
|
|
|
211
211
|
async function prepareLocalChatRun(io, pluginSet) {
|
|
212
212
|
defaultStateAdapterForLocalChat();
|
|
213
213
|
await configureLocalChatPlugins(pluginSet);
|
|
214
|
-
const { runLocalAgentTurn } = await import("../runner-
|
|
214
|
+
const { runLocalAgentTurn } = await import("../runner-Y73GZ2VE.js");
|
|
215
215
|
const deps = {
|
|
216
216
|
agentRunner: createAgentRunner(executeAgentRun),
|
|
217
217
|
deliverReply: async (reply) => {
|
package/dist/cli/plugins.js
CHANGED
package/dist/reporting.js
CHANGED
|
@@ -6,19 +6,19 @@ import {
|
|
|
6
6
|
getConversationDetails,
|
|
7
7
|
getConversationDetailsForIds,
|
|
8
8
|
resolveSlackConversationContextFromThreadId
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-PGR4WGZW.js";
|
|
10
10
|
import {
|
|
11
11
|
buildSystemPrompt
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-IWKVXO3F.js";
|
|
13
13
|
import {
|
|
14
14
|
getAgentTurnSessionRecord,
|
|
15
15
|
listAgentTurnSessionSummariesForConversation,
|
|
16
16
|
loadActivityEntries,
|
|
17
17
|
piContentMessageSchema
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-OQQU3SD6.js";
|
|
19
19
|
import {
|
|
20
20
|
getPluginOperationalReports
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-7K3JALTQ.js";
|
|
22
22
|
import "./chunk-OZJXGX4U.js";
|
|
23
23
|
import "./chunk-G3E7SCME.js";
|
|
24
24
|
import {
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
scheduleSessionCompletedPluginTasks,
|
|
9
9
|
updateConversationStats,
|
|
10
10
|
upsertConversationMessage
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-O6ZYIHFC.js";
|
|
12
12
|
import "./chunk-KNFROR7R.js";
|
|
13
13
|
import {
|
|
14
14
|
coerceThreadArtifactsState,
|
|
@@ -18,15 +18,15 @@ import {
|
|
|
18
18
|
markTurnFailed,
|
|
19
19
|
persistThreadStateById,
|
|
20
20
|
startActiveTurn
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-Z4FOYQXW.js";
|
|
22
22
|
import {
|
|
23
23
|
coerceThreadConversationState
|
|
24
24
|
} from "./chunk-PFXC67GJ.js";
|
|
25
25
|
import {
|
|
26
26
|
commitMessages,
|
|
27
27
|
loadProjection
|
|
28
|
-
} from "./chunk-
|
|
29
|
-
import "./chunk-
|
|
28
|
+
} from "./chunk-OQQU3SD6.js";
|
|
29
|
+
import "./chunk-7K3JALTQ.js";
|
|
30
30
|
import "./chunk-OZJXGX4U.js";
|
|
31
31
|
import "./chunk-G3E7SCME.js";
|
|
32
32
|
import "./chunk-ZATRYQLR.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sentry/junior",
|
|
3
|
-
"version": "0.92.
|
|
3
|
+
"version": "0.92.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
"pg": "^8.16.3",
|
|
79
79
|
"yaml": "^2.9.0",
|
|
80
80
|
"zod": "^4.4.3",
|
|
81
|
-
"@sentry/junior-plugin-api": "0.92.
|
|
81
|
+
"@sentry/junior-plugin-api": "0.92.1"
|
|
82
82
|
},
|
|
83
83
|
"devDependencies": {
|
|
84
84
|
"@emnapi/core": "^1.10.0",
|
|
@@ -94,9 +94,9 @@
|
|
|
94
94
|
"typescript": "^6.0.3",
|
|
95
95
|
"vercel": "^54.4.0",
|
|
96
96
|
"vitest": "^4.1.7",
|
|
97
|
-
"@sentry/junior-github": "0.92.
|
|
98
|
-
"@sentry/junior-memory": "0.92.
|
|
99
|
-
"@sentry/junior-scheduler": "0.92.
|
|
97
|
+
"@sentry/junior-github": "0.92.1",
|
|
98
|
+
"@sentry/junior-memory": "0.92.1",
|
|
99
|
+
"@sentry/junior-scheduler": "0.92.1",
|
|
100
100
|
"@sentry/junior-testing": "0.0.0"
|
|
101
101
|
},
|
|
102
102
|
"scripts": {
|