@sentry/junior 0.92.0 → 0.93.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{agent-hooks-BYSSWCNW.js → agent-hooks-ZG7IDOIN.js} +5 -5
- package/dist/api/people/list.js +3 -3
- package/dist/api/people/profile.js +3 -3
- package/dist/app.js +44 -15
- package/dist/chat/agent/tools.d.ts +2 -0
- package/dist/chat/pi/client.d.ts +1 -1
- package/dist/chat/pi/sdk.d.ts +7 -0
- package/dist/chat/plugins/agent-hooks.d.ts +2 -0
- package/dist/{chunk-H7KUZAMZ.js → chunk-6H4PP63X.js} +2 -2
- package/dist/{chunk-ZATRYQLR.js → chunk-7STN2ZSK.js} +1 -1
- package/dist/{chunk-OJP53WIU.js → chunk-HDNWZMUN.js} +3 -3
- package/dist/{chunk-7DVIELX3.js → chunk-JJUJ4CO2.js} +416 -415
- package/dist/{chunk-BMQ5DXHV.js → chunk-LE5ANBUZ.js} +2 -2
- package/dist/{chunk-N25HRI6B.js → chunk-LNCREA5Z.js} +2 -2
- package/dist/{chunk-ACJENBVF.js → chunk-MAVOJ54A.js} +7 -7
- package/dist/{chunk-3F54A3YM.js → chunk-NAPITCZ6.js} +12 -10
- package/dist/{chunk-NIFONS4W.js → chunk-NFXSLTYG.js} +1 -1
- package/dist/{chunk-TF5VLGA7.js → chunk-QGEWC27H.js} +2 -2
- package/dist/{chunk-7FS3K243.js → chunk-QL66APYJ.js} +4 -3
- package/dist/{chunk-OZJXGX4U.js → chunk-TNUUATT7.js} +1 -1
- package/dist/{chunk-VY7TVOIK.js → chunk-UUB3D2XI.js} +5 -3
- package/dist/{chunk-APIVR44P.js → chunk-YJ4OPVNA.js} +1 -1
- package/dist/cli/chat.js +13 -13
- package/dist/cli/plugins.js +5 -5
- package/dist/cli/snapshot-warmup.js +3 -3
- package/dist/cli/upgrade.js +5 -5
- package/dist/{db-GCK43OO3.js → db-YDN6AFJH.js} +2 -2
- package/dist/reporting.js +8 -8
- package/dist/{runner-XWTFA26U.js → runner-XAZPJNAQ.js} +8 -8
- package/package.json +8 -8
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
persistRunningSessionRecord,
|
|
12
12
|
persistTimeoutSessionRecord,
|
|
13
13
|
persistYieldSessionRecord
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-HDNWZMUN.js";
|
|
15
15
|
import {
|
|
16
16
|
JUNIOR_THREAD_STATE_TTL_MS
|
|
17
17
|
} from "./chunk-PFXC67GJ.js";
|
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
isSnapshotMissingError,
|
|
24
24
|
resolveRuntimeDependencySnapshot,
|
|
25
25
|
runNonInteractiveCommand
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-6H4PP63X.js";
|
|
27
27
|
import {
|
|
28
28
|
JUNIOR_PERSONALITY,
|
|
29
29
|
buildPluginSystemPromptContributions,
|
|
@@ -33,15 +33,17 @@ import {
|
|
|
33
33
|
formatSlackLink,
|
|
34
34
|
isNoReplyMarker,
|
|
35
35
|
stripNoReplyMarker
|
|
36
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-LE5ANBUZ.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-QL66APYJ.js";
|
|
45
47
|
import {
|
|
46
48
|
SlackActionError,
|
|
47
49
|
createPluginHookRunner,
|
|
@@ -58,10 +60,10 @@ import {
|
|
|
58
60
|
normalizeSlackConversationId,
|
|
59
61
|
resolveChannelCapabilities,
|
|
60
62
|
withSlackRetries
|
|
61
|
-
} from "./chunk-
|
|
63
|
+
} from "./chunk-UUB3D2XI.js";
|
|
62
64
|
import {
|
|
63
65
|
createPluginLogger
|
|
64
|
-
} from "./chunk-
|
|
66
|
+
} from "./chunk-TNUUATT7.js";
|
|
65
67
|
import {
|
|
66
68
|
SANDBOX_DATA_ROOT,
|
|
67
69
|
SANDBOX_SKILLS_ROOT,
|
|
@@ -72,11 +74,11 @@ import {
|
|
|
72
74
|
import {
|
|
73
75
|
acquireActiveLock,
|
|
74
76
|
getStateAdapter
|
|
75
|
-
} from "./chunk-
|
|
77
|
+
} from "./chunk-7STN2ZSK.js";
|
|
76
78
|
import {
|
|
77
79
|
getConversationStore,
|
|
78
80
|
getDb
|
|
79
|
-
} from "./chunk-
|
|
81
|
+
} from "./chunk-NFXSLTYG.js";
|
|
80
82
|
import {
|
|
81
83
|
GEN_AI_PROVIDER_NAME,
|
|
82
84
|
GEN_AI_SERVER_ADDRESS,
|
|
@@ -101,7 +103,7 @@ import {
|
|
|
101
103
|
renderCurrentInstruction,
|
|
102
104
|
resolveGatewayModel,
|
|
103
105
|
stripRuntimeTurnContext
|
|
104
|
-
} from "./chunk-
|
|
106
|
+
} from "./chunk-NAPITCZ6.js";
|
|
105
107
|
import {
|
|
106
108
|
parseSlackThreadId,
|
|
107
109
|
resolveConversationPrivacy,
|
|
@@ -451,7 +453,7 @@ var SkillSandbox = class {
|
|
|
451
453
|
// src/chat/pi/traced-stream.ts
|
|
452
454
|
import {
|
|
453
455
|
streamSimple
|
|
454
|
-
} from "@earendil-works/pi-ai";
|
|
456
|
+
} from "@earendil-works/pi-ai/compat";
|
|
455
457
|
function attributeModeForPrivacy(conversationPrivacy) {
|
|
456
458
|
return conversationPrivacy === "public" ? "content" : "metadata";
|
|
457
459
|
}
|
|
@@ -8077,7 +8079,7 @@ function createWebFetchTool(hooks, options = {}) {
|
|
|
8077
8079
|
import { z as z35 } from "zod";
|
|
8078
8080
|
import { generateText } from "ai";
|
|
8079
8081
|
import { createGatewayProvider } from "@ai-sdk/gateway";
|
|
8080
|
-
import { getModel } from "@earendil-works/pi-ai";
|
|
8082
|
+
import { getModel } from "@earendil-works/pi-ai/compat";
|
|
8081
8083
|
var SEARCH_TIMEOUT_MS = 6e4;
|
|
8082
8084
|
var MAX_RESULTS2 = 5;
|
|
8083
8085
|
var DEFAULT_SEARCH_MODEL = getModel("vercel-ai-gateway", "openai/gpt-5.4").id;
|
|
@@ -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,
|