@sentry/junior 0.256.0 → 0.258.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/{actor-BTtLaeWy.js → actor-tlxzqaRe.js} +3 -6
- package/dist/{admin-BhucwVfy.js → admin-My1SLGVO.js} +2 -3
- package/dist/{agent-hooks-DlSK8PQQ.js → agent-hooks-BJ_5mlRH.js} +71 -111
- package/dist/{agent-invocations-BY60iNw-.js → agent-invocations-Qfz7dWgU.js} +8 -13
- package/dist/{agent-runner-C6_cd61V.js → agent-runner-DGsFQw72.js} +278 -467
- package/dist/api/schema.d.ts +454 -448
- package/dist/api/schema.js +5 -5
- package/dist/api.d.ts +2 -12
- package/dist/api.js +189 -165
- package/dist/{app-B0gT1Slp.d.ts → app-PX2H1PxU.d.ts} +20 -37
- package/dist/app.d.ts +3 -3
- package/dist/app.js +565 -305
- package/dist/{assistant-reply-yn5G-YEG.js → assistant-reply-H1M-91oF.js} +3 -5
- package/dist/{automation-CHdlHVZP.js → automation-DWBFBenG.js} +6 -11
- package/dist/{briefs-U6Bi3IYw.js → briefs-vYoK85rJ.js} +8 -11
- package/dist/{cadence-D00SCzT1.js → cadence-R7Em4RjE.js} +1 -2
- package/dist/{catalog-runtime-DF5OWqCc.js → catalog-runtime-BN4DVxco.js} +3 -4
- package/dist/cli/chat.d.ts +2 -4
- package/dist/cli/chat.js +22 -24
- package/dist/cli/check.d.ts +1 -3
- package/dist/cli/check.js +4 -5
- package/dist/cli/env.d.ts +1 -3
- package/dist/cli/env.js +1 -2
- package/dist/cli/init.d.ts +1 -3
- package/dist/cli/init.js +3 -3
- package/dist/cli/main.d.ts +1 -3
- package/dist/cli/main.js +4 -5
- package/dist/cli/plugins.d.ts +2 -4
- package/dist/cli/plugins.js +7 -8
- package/dist/cli/run.d.ts +1 -2
- package/dist/cli/run.js +1 -2
- package/dist/cli/snapshot-create.d.ts +1 -3
- package/dist/cli/snapshot-create.js +4 -5
- package/dist/cli/upgrade.d.ts +3 -6
- package/dist/cli/upgrade.js +11 -17
- package/dist/{client-BVrAp-pq.js → client-DbyHuMFU.js} +9 -16
- package/dist/{config-DdBiDanf.js → config-_WO_AjCB.js} +18 -15
- package/dist/{connections-CG04HdpC.js → connections-ag_1JOhB.js} +21 -21
- package/dist/{conversation-T18Xlkx9.js → conversation-DjN3mlog.js} +11 -17
- package/dist/{conversation-privacy-CpSYOWnP.js → conversation-privacy-DHP_xnVj.js} +2 -3
- package/dist/{conversation-work-C6y3T5Hx.js → conversation-work-BaT_T6EB.js} +1 -2
- package/dist/{credential-sync-DKWNdcgm.js → credential-sync-B-CPX_ag.js} +89 -52
- package/dist/{db-Ca9Nt5ci.d.ts → db-BnRqQ7G5.d.ts} +1 -1
- package/dist/{executor-BroK9oKy.js → executor-RvG6kVe1.js} +58 -70
- package/dist/{experimental-Qn9rKLgx.js → experimental-BNK1l1jv.js} +2 -3
- package/dist/{history-9pO1Zd4Y.js → history-AY8rs-FR.js} +5 -9
- package/dist/{history-DvqWZlYX.d.ts → history-BgI33Kie.d.ts} +12 -20
- package/dist/{images-D0VZ5nv0.js → images-C2J_bj2g.js} +5 -6
- package/dist/instrumentation.d.ts +1 -3
- package/dist/instrumentation.js +6 -8
- package/dist/{job-queue-BbGg3gvu.js → job-queue-DVe37it2.js} +6 -12
- package/dist/{logging-tPQeUe2i.js → logging-DsHONhVm.js} +54 -24
- package/dist/{message-DdPGRYQP.js → message-DyitL8no.js} +5 -6
- package/dist/{model-profile-BwU8mqwD.js → model-profile-Bg8EoCKD.js} +2 -4
- package/dist/nitro.d.ts +3 -5
- package/dist/nitro.js +12 -17
- package/dist/{oauth-authorization-BA4Dt6a7.js → oauth-authorization-djQn5Nhy.js} +2 -4
- package/dist/{oauth-callback-server-B-2errCX.js → oauth-callback-server-CDby-pCn.js} +3 -4
- package/dist/{oauth-relay-CdCnu80W.js → oauth-relay-CTygMkNx.js} +2 -3
- package/dist/{package-discovery-BVvSnQBB.js → package-discovery-DJBompdd.js} +17 -21
- package/dist/{pending-auth-DT3MRVW8.js → pending-auth-D8J1uJUS.js} +37 -28
- package/dist/{plugin-module-CVvEUSMH.js → plugin-module-Cf5gVPWP.js} +1 -2
- package/dist/{plugins-CjfUP5gJ.d.ts → plugins-B11Mfkmv.d.ts} +0 -4
- package/dist/{plugins-egKWjgue.js → plugins-DOm9Y6qI.js} +2 -3
- package/dist/{private-trace-result-BLvBjy_e.js → private-trace-result-CE7_lEdq.js} +1 -2
- package/dist/{profile-Bb1zCVGP.js → profile-DpYjfKke.js} +16 -28
- package/dist/{prompt-C04mP1hu.js → prompt-xgpyMtg7.js} +5 -9
- package/dist/{queue-B5SnqRln.d.ts → queue-C37RbDVc.d.ts} +0 -2
- package/dist/{registry-CsNavQ_Z.js → registry-Du566MtJ.js} +57 -30
- package/dist/{resolve-B6ZZ9duG.js → resolve-ClCIgh8E.js} +7 -12
- package/dist/{result-j9nS0se-.js → result-BBbKA61B.js} +13 -17
- package/dist/{rolldown-runtime-B4FMCO8f.js → rolldown-runtime-nwUcYXjP.js} +1 -2
- package/dist/{runner-Y331DoZ5.js → runner-CCuqFSqx.js} +12 -13
- package/dist/{sandbox-egress-signals-BUfjEdHY.js → sandbox-egress-signals-DY1mbKF4.js} +2 -3
- package/dist/{schema-BBgv0MNf.js → schema-DrMh3NtR.js} +17 -27
- package/dist/{sentry-CgWZM_kV.js → sentry-BBUlHih9.js} +2 -3
- package/dist/{session-stop-q-6GNHx6.js → session-stop-CIoFiwwe.js} +57 -41
- package/dist/{skills-CyvTsR9M.js → skills-DyQBLIrK.js} +9 -9
- package/dist/{spawn-Do5mX3d_.js → spawn-Dqfeo7XP.js} +4 -5
- package/dist/{store-DoewL5mG.d.ts → store-CG0VJyye.d.ts} +0 -14
- package/dist/{store-D2It0ozF.js → store-DJLwq4x8.js} +13 -15
- package/dist/{task-queue-ZMk9bLRT.js → task-queue-BzW4MaWU.js} +5 -7
- package/dist/{task-runner-cIGU5VwJ.js → task-runner-D3qJh4fK.js} +22 -26
- package/dist/{tasks-CODtRzvX.js → tasks-CEXKTASS.js} +78 -79
- package/dist/{thread-state-BPkwVmvK.js → thread-state-W3f6kAtz.js} +13 -19
- package/dist/{turn-failure-response-ChmMeKar.js → turn-failure-response-CWx7aNIh.js} +16 -22
- package/dist/{turn-lifecycle-BUP7ZOVa.js → turn-lifecycle-C9JFst7-.js} +2 -3
- package/dist/{turn-session-routing-BcWM3PLm.js → turn-session-routing-CUxtfpr7.js} +2 -3
- package/dist/{validation-DCd69-cP.js → validation-BHRxa5G4.js} +3 -4
- package/dist/vercel.d.ts +1 -3
- package/dist/vercel.js +1 -2
- package/dist/{version-DBc4Qt_P.js → version-C0U6rHg0.js} +3 -5
- package/dist/{version-CnXZ614E.d.ts → version-Cc2OFd9G.d.ts} +0 -2
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -2
- package/dist/{viewer-C-9nFKYr.js → viewer-CGvvRqKp.js} +61 -44
- package/dist/{web-input-Cv42P3ni.js → web-input-Keb5GRWj.js} +139 -198
- package/dist/{web-message-id-xPI_EFSC.js → web-message-id-CJSUiksE.js} +3 -6
- package/dist/{work-6UmVQq1V.js → work-DRcsJ3hV.js} +14 -16
- package/dist/{worker-DAoBZuZn.js → worker-Cjo-QqPq.js} +7 -8
- package/migrations/0059_automation_run_version.sql +2 -0
- package/migrations/0060_identity_signed_in_at.sql +1 -0
- package/migrations/meta/0059_snapshot.json +3619 -0
- package/migrations/meta/0060_snapshot.json +3465 -0
- package/migrations/meta/_journal.json +15 -1
- package/package.json +8 -6
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as toCanonicalInputMessage, n as getCurrentConversationPrivacy, o as toCanonicalOutputMessage, s as toGenAiMessagesTraceAttributes } from "./conversation-privacy-
|
|
1
|
+
import { T as withSpan, _ as serializeGenAiAttribute, f as logException, h as normalizeGenAiFinishReason, i as extractGenAiUsageAttributes, m as logWarn } from "./logging-DsHONhVm.js";
|
|
2
|
+
import { a as toCanonicalInputMessage, n as getCurrentConversationPrivacy, o as toCanonicalOutputMessage, s as toGenAiMessagesTraceAttributes } from "./conversation-privacy-DHP_xnVj.js";
|
|
3
3
|
import { calculateCost, completeSimple, getEnvApiKey, getModels, registerApiProvider } from "@earendil-works/pi-ai/compat";
|
|
4
4
|
import { stream as streamAnthropic, streamSimple as streamSimpleAnthropic } from "@earendil-works/pi-ai/api/anthropic-messages";
|
|
5
5
|
import { createGatewayProvider } from "@ai-sdk/gateway";
|
|
6
6
|
import { getVercelOidcToken } from "@vercel/oidc";
|
|
7
7
|
import { NoObjectGeneratedError, embedMany, generateObject } from "ai";
|
|
8
|
-
|
|
8
|
+
// src/chat/optional-string.ts
|
|
9
9
|
/**
|
|
10
10
|
* Normalize optional env-style strings so blank values do not masquerade as
|
|
11
11
|
* configured inputs.
|
|
@@ -15,8 +15,7 @@ function toOptionalTrimmed(value) {
|
|
|
15
15
|
const trimmed = value.trim();
|
|
16
16
|
return trimmed.length > 0 ? trimmed : void 0;
|
|
17
17
|
}
|
|
18
|
-
|
|
19
|
-
//#region src/chat/pi/gateway-auth.ts
|
|
18
|
+
// src/chat/pi/gateway-auth.ts
|
|
20
19
|
/**
|
|
21
20
|
* AI Gateway credential resolution for every Junior model path.
|
|
22
21
|
*
|
|
@@ -51,8 +50,7 @@ async function resolveGatewayCredential() {
|
|
|
51
50
|
async function getGatewayApiKey() {
|
|
52
51
|
return (await resolveGatewayCredential())?.token;
|
|
53
52
|
}
|
|
54
|
-
|
|
55
|
-
//#region src/chat/services/provider-error.ts
|
|
53
|
+
// src/chat/services/provider-error.ts
|
|
56
54
|
/** Structured failure produced at an AI provider boundary. */
|
|
57
55
|
var ProviderError = class extends Error {
|
|
58
56
|
code = "provider_error";
|
|
@@ -227,8 +225,7 @@ function getProviderErrorAttributes(error) {
|
|
|
227
225
|
...error.modelId ? { "gen_ai.request.model": error.modelId } : void 0
|
|
228
226
|
};
|
|
229
227
|
}
|
|
230
|
-
|
|
231
|
-
//#region src/chat/xml.ts
|
|
228
|
+
// src/chat/xml.ts
|
|
232
229
|
function escapeXml(value) {
|
|
233
230
|
return value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll("\"", """).replaceAll("'", "'");
|
|
234
231
|
}
|
|
@@ -236,8 +233,7 @@ function escapeXml(value) {
|
|
|
236
233
|
function unescapeXml(value) {
|
|
237
234
|
return value.replaceAll(""", "\"").replaceAll("'", "'").replaceAll(">", ">").replaceAll("<", "<").replaceAll("&", "&");
|
|
238
235
|
}
|
|
239
|
-
|
|
240
|
-
//#region src/chat/current-instruction.ts
|
|
236
|
+
// src/chat/current-instruction.ts
|
|
241
237
|
const CURRENT_INSTRUCTION_TAG = "current-instruction";
|
|
242
238
|
const CURRENT_INSTRUCTION_OPEN_PREFIX = `<${CURRENT_INSTRUCTION_TAG}`;
|
|
243
239
|
const CURRENT_INSTRUCTION_OPEN_BARE = `<${CURRENT_INSTRUCTION_TAG}>`;
|
|
@@ -275,8 +271,7 @@ function unwrapCurrentInstruction(text) {
|
|
|
275
271
|
const body = readCurrentInstructionBody(text);
|
|
276
272
|
return body === void 0 ? void 0 : unescapeXml(body);
|
|
277
273
|
}
|
|
278
|
-
|
|
279
|
-
//#region src/chat/services/context-compaction-marker.ts
|
|
274
|
+
// src/chat/services/context-compaction-marker.ts
|
|
280
275
|
const COMPACTION_SUMMARY_PREFIX = "Another language model started to solve this problem and produced a summary of its thinking process. You also have access to the state of the tools that were used by that language model. Use this to build on the work that has already been done and avoid duplicating work. Here is the summary produced by the other language model, use the information in this summary to assist with your own analysis:";
|
|
281
276
|
/** Return whether text is one of Junior's durable compacted-context markers. */
|
|
282
277
|
function isCompactionSummaryText(text) {
|
|
@@ -292,8 +287,7 @@ function hasCompactedConversationContext(messages) {
|
|
|
292
287
|
return content.some((part) => part && typeof part === "object" && part.type === "text" && typeof part.text === "string" && isCompactionSummaryText(part.text));
|
|
293
288
|
});
|
|
294
289
|
}
|
|
295
|
-
|
|
296
|
-
//#region src/chat/pi/client.ts
|
|
290
|
+
// src/chat/pi/client.ts
|
|
297
291
|
registerApiProvider({
|
|
298
292
|
api: "anthropic-messages",
|
|
299
293
|
stream: streamAnthropic,
|
|
@@ -671,5 +665,4 @@ async function embedTexts(params) {
|
|
|
671
665
|
throw providerError;
|
|
672
666
|
}
|
|
673
667
|
}
|
|
674
|
-
//#endregion
|
|
675
668
|
export { toOptionalTrimmed as S, getProviderErrorUserMessage as _, embedTexts as a, getGatewayApiKey as b, hasCompactedConversationContext as c, unwrapCurrentInstruction as d, escapeXml as f, getProviderErrorAttributes as g, findProviderError as h, completeText as i, isCompactionSummaryText as l, createProviderError as m, GEN_AI_SERVER_ADDRESS as n, resolveGatewayModel as o, ProviderError as p, completeObject as r, COMPACTION_SUMMARY_PREFIX as s, GEN_AI_PROVIDER_NAME as t, renderCurrentInstruction as u, isProviderRetryError as v, resolveGatewayCredential as x, MISSING_GATEWAY_CREDENTIALS_ERROR as y };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { t as __exportAll } from "./rolldown-runtime-
|
|
2
|
-
import { S as toOptionalTrimmed, o as resolveGatewayModel } from "./client-
|
|
3
|
-
import {
|
|
4
|
-
import { l as TURN_REASONING_LEVELS, s as modelProfileSchema, t as DEFAULT_MODEL_PROFILES, u as parseTurnReasoningLevel } from "./model-profile-
|
|
5
|
-
|
|
1
|
+
import { t as __exportAll } from "./rolldown-runtime-nwUcYXjP.js";
|
|
2
|
+
import { S as toOptionalTrimmed, o as resolveGatewayModel } from "./client-DbyHuMFU.js";
|
|
3
|
+
import { m as logWarn } from "./logging-DsHONhVm.js";
|
|
4
|
+
import { l as TURN_REASONING_LEVELS, s as modelProfileSchema, t as DEFAULT_MODEL_PROFILES, u as parseTurnReasoningLevel } from "./model-profile-Bg8EoCKD.js";
|
|
5
|
+
// src/chat/slack/emoji.ts
|
|
6
6
|
const SLACK_EMOJI_NAME_RE = /^(?:[a-z0-9_+-]+)(?:::(?:skin-tone-[2-6]))?$/;
|
|
7
7
|
function normalizeSlackEmojiName(value) {
|
|
8
8
|
const trimmed = value.trim().toLowerCase();
|
|
@@ -10,8 +10,7 @@ function normalizeSlackEmojiName(value) {
|
|
|
10
10
|
const normalized = trimmed.startsWith(":") && trimmed.endsWith(":") ? trimmed.slice(1, -1) : trimmed;
|
|
11
11
|
return SLACK_EMOJI_NAME_RE.test(normalized) ? normalized : null;
|
|
12
12
|
}
|
|
13
|
-
|
|
14
|
-
//#region src/chat/config.ts
|
|
13
|
+
// src/chat/config.ts
|
|
15
14
|
var config_exports = /* @__PURE__ */ __exportAll({
|
|
16
15
|
CONVERSATION_WORK_SOFT_YIELD_BUFFER_SECONDS: () => 40,
|
|
17
16
|
DEFAULT_SQL_STATEMENT_TIMEOUT_MS: () => DEFAULT_SQL_STATEMENT_TIMEOUT_MS,
|
|
@@ -60,12 +59,14 @@ const MAX_TOOL_CALLS_PER_TURN = 1e3;
|
|
|
60
59
|
*/
|
|
61
60
|
const MAX_CONSECUTIVE_AUTOMATED_TURNS = 25;
|
|
62
61
|
/**
|
|
63
|
-
* Max runs one Event automation can start in
|
|
64
|
-
* full agent turn, and Event automations skip the consecutive
|
|
65
|
-
* limit. Kept low so a broad trigger, such as every message in
|
|
66
|
-
* blocks quickly instead of starting a turn for each Event.
|
|
62
|
+
* Max runs one Event automation can start in one rolling run window. Each run
|
|
63
|
+
* is a full agent turn, and Event automations skip the consecutive
|
|
64
|
+
* automated-turn limit. Kept low so a broad trigger, such as every message in
|
|
65
|
+
* a channel, blocks quickly instead of starting a turn for each Event.
|
|
67
66
|
*/
|
|
68
|
-
const
|
|
67
|
+
const MAX_EVENT_AUTOMATION_RUNS = 10;
|
|
68
|
+
/** Length of the rolling window for the Event automation run limit. */
|
|
69
|
+
const EVENT_AUTOMATION_RUN_WINDOW_MS = 6e4;
|
|
69
70
|
const DEFAULT_FUNCTION_MAX_DURATION_SECONDS = 300;
|
|
70
71
|
const DEFAULT_SLACK_SLASH_COMMAND = "/jr";
|
|
71
72
|
const DEFAULT_PROCESSING_REACTION_EMOJI = "eyes";
|
|
@@ -270,7 +271,8 @@ function readBotConfig(env, functionMaxDurationSeconds) {
|
|
|
270
271
|
maxToolCallsPerTurn: MAX_TOOL_CALLS_PER_TURN,
|
|
271
272
|
maxTurnCostUsd: MAX_TURN_COST_USD,
|
|
272
273
|
maxConsecutiveAutomatedTurns: MAX_CONSECUTIVE_AUTOMATED_TURNS,
|
|
273
|
-
|
|
274
|
+
maxEventAutomationRuns: MAX_EVENT_AUTOMATION_RUNS,
|
|
275
|
+
eventAutomationRunWindowMs: EVENT_AUTOMATION_RUN_WINDOW_MS,
|
|
274
276
|
turnTimeoutMs: parseAgentTurnTimeoutMs(env.AGENT_TURN_TIMEOUT_MS, maxTurnTimeoutMs),
|
|
275
277
|
webSearchModelId: validateGatewayModelId(env.AI_WEB_SEARCH_MODEL) ?? DEFAULT_WEB_SEARCH_MODEL_ID
|
|
276
278
|
};
|
|
@@ -384,7 +386,9 @@ function setRuntimeLimits(limits) {
|
|
|
384
386
|
bot.maxAgentDepth = limits.maxAgentDepth;
|
|
385
387
|
}
|
|
386
388
|
if (limits?.maxConsecutiveAutomatedTurns !== void 0) bot.maxConsecutiveAutomatedTurns = requirePositiveLimit("maxConsecutiveAutomatedTurns", limits.maxConsecutiveAutomatedTurns);
|
|
387
|
-
|
|
389
|
+
const runLimit = limits?.eventAutomationRunLimit;
|
|
390
|
+
if (runLimit?.maxRuns !== void 0) bot.maxEventAutomationRuns = requirePositiveLimit("eventAutomationRunLimit.maxRuns", runLimit.maxRuns);
|
|
391
|
+
if (runLimit?.windowMs !== void 0) bot.eventAutomationRunWindowMs = requirePositiveLimit("eventAutomationRunLimit.windowMs", runLimit.windowMs);
|
|
388
392
|
if (limits?.maxSlicesPerTurn !== void 0) bot.maxSlicesPerTurn = requirePositiveLimit("maxSlicesPerTurn", limits.maxSlicesPerTurn);
|
|
389
393
|
if (limits?.maxToolCallsPerTurn !== void 0) bot.maxToolCallsPerTurn = requirePositiveLimit("maxToolCallsPerTurn", limits.maxToolCallsPerTurn);
|
|
390
394
|
if (limits?.maxTurnCostUsd !== void 0) bot.maxTurnCostUsd = requirePositiveLimit("maxTurnCostUsd", limits.maxTurnCostUsd);
|
|
@@ -440,5 +444,4 @@ function setSlackReactionConfig(overrides) {
|
|
|
440
444
|
if (overrides.processingReactionEmoji !== void 0) chatConfig.slack.processingReactionEmoji = parseReactionEmoji("processingReactionEmoji", overrides.processingReactionEmoji, chatConfig.slack.processingReactionEmoji);
|
|
441
445
|
if (overrides.completedReactionEmoji !== void 0) chatConfig.slack.completedReactionEmoji = parseReactionEmoji("completedReactionEmoji", overrides.completedReactionEmoji, chatConfig.slack.completedReactionEmoji);
|
|
442
446
|
}
|
|
443
|
-
//#endregion
|
|
444
447
|
export { snapshotRuntimeConfig as _, getRuntimeMetadata as a, getSlackClientSecret as c, restoreRuntimeConfig as d, setBotModelConfig as f, setSlackReactionConfig as g, setRuntimeLimits as h, getChatConfig as i, getSlackSigningSecret as l, setProfiles as m, botConfig as n, getSlackBotToken as o, setCrossActorMidRunMode as p, config_exports as r, getSlackClientId as s, DEFAULT_SQL_STATEMENT_TIMEOUT_MS as t, resetRuntimeConfig as u, normalizeSlackEmojiName as v };
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { It as startOAuthFlow, c as deleteMcpAuthSessionsForUserProvider, l as deleteMcpServerSessionId, u as deleteMcpStoredOAuthCredentials } from "./agent-runner-
|
|
2
|
-
import {
|
|
3
|
-
import { u as hasRequiredOAuthScope } from "./registry-
|
|
4
|
-
import { n as pluginCatalogRuntime } from "./catalog-runtime-
|
|
5
|
-
import {
|
|
6
|
-
import { w as getStateAdapter } from "./profile-
|
|
7
|
-
import { a as getVercelConversationWorkQueue } from "./job-queue-
|
|
8
|
-
import { m as ensureConversationWake, w as requestConversationWork } from "./store-
|
|
9
|
-
import { n as resolveTurnSessionRouting } from "./turn-session-routing-
|
|
1
|
+
import { It as startOAuthFlow, c as deleteMcpAuthSessionsForUserProvider, l as deleteMcpServerSessionId, u as deleteMcpStoredOAuthCredentials } from "./agent-runner-DGsFQw72.js";
|
|
2
|
+
import { A as deleteProviderIdentityForUser, c as getConversationEventStore, f as getSqlExecutor, k as deleteProviderIdentityForSlackUser } from "./viewer-CGvvRqKp.js";
|
|
3
|
+
import { u as hasRequiredOAuthScope } from "./registry-Du566MtJ.js";
|
|
4
|
+
import { n as pluginCatalogRuntime } from "./catalog-runtime-BN4DVxco.js";
|
|
5
|
+
import { K as loadTurnCheckpoint, X as failTurnRecord, Z as getTurnRecord } from "./tasks-CEXKTASS.js";
|
|
6
|
+
import { w as getStateAdapter } from "./profile-DpYjfKke.js";
|
|
7
|
+
import { a as getVercelConversationWorkQueue } from "./job-queue-DVe37it2.js";
|
|
8
|
+
import { m as ensureConversationWake, w as requestConversationWork } from "./store-DJLwq4x8.js";
|
|
9
|
+
import { n as resolveTurnSessionRouting } from "./turn-session-routing-CUxtfpr7.js";
|
|
10
10
|
import { z } from "zod";
|
|
11
11
|
import { randomBytes, randomUUID } from "node:crypto";
|
|
12
|
-
|
|
12
|
+
// src/chat/task-execution/authorized-turn.ts
|
|
13
13
|
/**
|
|
14
14
|
* OAuth callbacks save readiness, not agent history. The conversation worker
|
|
15
15
|
* consumes this event under its lease before it resumes the paused Turn.
|
|
@@ -56,8 +56,7 @@ async function getTurnAuthorization(turn) {
|
|
|
56
56
|
if (event?.data.type !== "structured_event") return void 0;
|
|
57
57
|
return authorizationSchema.parse(event.data.content);
|
|
58
58
|
}
|
|
59
|
-
|
|
60
|
-
//#region src/chat/task-execution/turn-wake.ts
|
|
59
|
+
// src/chat/task-execution/turn-wake.ts
|
|
61
60
|
/** Build the worker input for a paused turn. */
|
|
62
61
|
async function getPausedTurnRequest(args) {
|
|
63
62
|
const turn = (await loadTurnCheckpoint({
|
|
@@ -126,8 +125,7 @@ async function wakeAuthorizedTurn(args, queue) {
|
|
|
126
125
|
const request = await recordTurnAuthorization(args);
|
|
127
126
|
if (request) await wakePausedTurn(request, { queue });
|
|
128
127
|
}
|
|
129
|
-
|
|
130
|
-
//#region src/chat/conversations/web-authorization.ts
|
|
128
|
+
// src/chat/conversations/web-authorization.ts
|
|
131
129
|
const WEB_AUTHORIZATION_PREFIX = "junior:web_authorization:v1";
|
|
132
130
|
const WEB_AUTHORIZATION_TTL_MS = 864e5;
|
|
133
131
|
function authorizationKey(conversationId, actorId) {
|
|
@@ -161,8 +159,7 @@ async function getWebAuthorization(args) {
|
|
|
161
159
|
async function deleteWebAuthorization(args) {
|
|
162
160
|
await getStateAdapter().delete(authorizationKey(args.conversationId, args.actorId));
|
|
163
161
|
}
|
|
164
|
-
|
|
165
|
-
//#region src/chat/credentials/unlink-provider.ts
|
|
162
|
+
// src/chat/credentials/unlink-provider.ts
|
|
166
163
|
/** Remove one provider connection and its exact stored account identity. */
|
|
167
164
|
async function unlinkProvider(userId, provider, userTokenStore, slackTeamId) {
|
|
168
165
|
const tokens = await userTokenStore.get(userId, provider);
|
|
@@ -174,8 +171,7 @@ async function unlinkProvider(userId, provider, userTokenStore, slackTeamId) {
|
|
|
174
171
|
deleteMcpAuthSessionsForUserProvider(userId, provider)
|
|
175
172
|
]);
|
|
176
173
|
}
|
|
177
|
-
|
|
178
|
-
//#region src/chat/credentials/connections.ts
|
|
174
|
+
// src/chat/credentials/connections.ts
|
|
179
175
|
/** Return stored OAuth tokens only when they still carry the manifest scope. */
|
|
180
176
|
async function readConnectedOAuthTokens(userId, plugin, userTokenStore) {
|
|
181
177
|
if (!plugin.manifest.oauth && !plugin.manifest.credentials) return;
|
|
@@ -231,9 +227,13 @@ async function startConnection(provider, actor) {
|
|
|
231
227
|
authorizationUrl: request.authorizationUrl
|
|
232
228
|
};
|
|
233
229
|
}
|
|
234
|
-
/**
|
|
235
|
-
|
|
230
|
+
/**
|
|
231
|
+
* Remove the user's stored connection for one provider and the provider
|
|
232
|
+
* identity that the connection linked to the viewer's user.
|
|
233
|
+
*/
|
|
234
|
+
async function disconnectConnection(userId, provider, userTokenStore, viewerUserId) {
|
|
235
|
+
const tokens = await userTokenStore.get(userId, provider);
|
|
236
|
+
if (tokens?.account) await deleteProviderIdentityForUser(getSqlExecutor(), viewerUserId, provider, tokens.account.id);
|
|
236
237
|
await unlinkProvider(userId, provider, userTokenStore);
|
|
237
238
|
}
|
|
238
|
-
//#endregion
|
|
239
239
|
export { startConnection as a, deleteWebAuthorization as c, getPausedTurnRequest as d, wakeAuthorizedTurn as f, readConnectedOAuthTokens as i, getWebAuthorization as l, getTurnAuthorization as m, isConnectableProvider as n, unlinkProvider as o, wakePausedTurn as p, listConnections as r, createWebAuthorization as s, disconnectConnection as t, createPausedTurns as u };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { a as conversationTurnFailureReasonSchema, h as usageSchema, i as conversationTurnFailureCodeSchema } from "./history-
|
|
1
|
+
import { a as conversationTurnFailureReasonSchema, h as usageSchema, i as conversationTurnFailureCodeSchema } from "./history-AY8rs-FR.js";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { codeChangeStateSchema, conversationAnnotationInputSchema, conversationEventPresentationSchema, conversationSidebarAnnotationSchema, objectFactFields, objectTypeSchema } from "@sentry/junior-plugin-api";
|
|
4
|
-
|
|
4
|
+
// src/chat/automations/card.ts
|
|
5
5
|
/** Saved automation facts shown with a Message, not a live status view. */
|
|
6
6
|
const automationCardSchema = z.object({
|
|
7
7
|
kind: z.literal("automation"),
|
|
@@ -23,8 +23,7 @@ function automationCardText(card) {
|
|
|
23
23
|
`Automation ID: ${card.id}`
|
|
24
24
|
].filter(Boolean).join("\n");
|
|
25
25
|
}
|
|
26
|
-
|
|
27
|
-
//#region src/chat/conversations/cards.ts
|
|
26
|
+
// src/chat/conversations/cards.ts
|
|
28
27
|
const storedCardSchema = automationCardSchema.extend({ operation: z.enum([
|
|
29
28
|
"created",
|
|
30
29
|
"updated",
|
|
@@ -93,8 +92,7 @@ function annotationCard(annotation) {
|
|
|
93
92
|
title: value.label
|
|
94
93
|
};
|
|
95
94
|
}
|
|
96
|
-
|
|
97
|
-
//#region src/chat/briefs/schema.ts
|
|
95
|
+
// src/chat/briefs/schema.ts
|
|
98
96
|
/**
|
|
99
97
|
* Runtime schemas for the Brief record and the generator input. Both cross a
|
|
100
98
|
* durable or CLI edge, so these schemas own the exported types.
|
|
@@ -211,8 +209,7 @@ function parseBriefInput(input) {
|
|
|
211
209
|
entries: [...parsed.entries].sort((left, right) => left.index - right.index || left.createdAtMs - right.createdAtMs)
|
|
212
210
|
};
|
|
213
211
|
}
|
|
214
|
-
|
|
215
|
-
//#region src/chat/attachments/media.ts
|
|
212
|
+
// src/chat/attachments/media.ts
|
|
216
213
|
const INPUT_IMAGE_TYPES = [
|
|
217
214
|
"image/png",
|
|
218
215
|
"image/jpeg",
|
|
@@ -294,8 +291,7 @@ function isVisionImageMediaType(mediaType) {
|
|
|
294
291
|
const normalized = mediaType.split(";", 1)[0]?.trim().toLowerCase();
|
|
295
292
|
return normalized ? INPUT_IMAGE_TYPES.some((type) => type === normalized) : false;
|
|
296
293
|
}
|
|
297
|
-
|
|
298
|
-
//#region src/chat/attachments/input.ts
|
|
294
|
+
// src/chat/attachments/input.ts
|
|
299
295
|
/** Bound JSON image input below the hosting platform's request size limit. */
|
|
300
296
|
const MAX_INPUT_IMAGE_BYTES = 3145728;
|
|
301
297
|
const MAX_INPUT_IMAGES = 3;
|
|
@@ -316,8 +312,7 @@ const messageAttachmentSchema = z.object({
|
|
|
316
312
|
function readMessageAttachments(value) {
|
|
317
313
|
return messageAttachmentSchema.array().parse(value ?? []);
|
|
318
314
|
}
|
|
319
|
-
|
|
320
|
-
//#region src/api/schema/child-agent-totals.ts
|
|
315
|
+
// src/api/schema/child-agent-totals.ts
|
|
321
316
|
/**
|
|
322
317
|
* The part of a Conversation total that its child agents spent, at any depth.
|
|
323
318
|
* Present only when the Conversation has child agents. The Conversation's own
|
|
@@ -329,8 +324,7 @@ const conversationChildAgentTotalsSchema = z.object({
|
|
|
329
324
|
cumulativeDurationMs: z.number(),
|
|
330
325
|
cumulativeUsage: usageSchema.optional()
|
|
331
326
|
}).strict();
|
|
332
|
-
|
|
333
|
-
//#region src/api/schema/conversation.ts
|
|
327
|
+
// src/api/schema/conversation.ts
|
|
334
328
|
const conversationReportStatusSchema = z.enum([
|
|
335
329
|
"active",
|
|
336
330
|
"completed",
|
|
@@ -528,6 +522,7 @@ const conversationReportMessageEventDataSchema = z.object({
|
|
|
528
522
|
]),
|
|
529
523
|
source: z.enum(["slack", "web"]).optional(),
|
|
530
524
|
actorIdentity: actorIdentitySchema.optional(),
|
|
525
|
+
mentions: z.array(actorIdentitySchema).optional(),
|
|
531
526
|
eventType: z.string().min(1).optional(),
|
|
532
527
|
eventObjectType: objectTypeSchema.optional(),
|
|
533
528
|
explicitMention: z.boolean().optional(),
|
|
@@ -541,9 +536,9 @@ const conversationReportMessageEventDataSchema = z.object({
|
|
|
541
536
|
code: "custom",
|
|
542
537
|
message: "message content must be text or explicitly redacted"
|
|
543
538
|
});
|
|
544
|
-
if (data.redacted && (data.actorIdentity || data.cards || data.attachments)) context.addIssue({
|
|
539
|
+
if (data.redacted && (data.actorIdentity || data.mentions || data.cards || data.attachments)) context.addIssue({
|
|
545
540
|
code: "custom",
|
|
546
|
-
message: "redacted messages must not expose actor identity, cards, or attachments"
|
|
541
|
+
message: "redacted messages must not expose actor identity, mentions, cards, or attachments"
|
|
547
542
|
});
|
|
548
543
|
});
|
|
549
544
|
const conversationReportMessageHandledEventDataSchema = z.object({
|
|
@@ -959,5 +954,4 @@ const conversationStatsReportSchema = z.object({
|
|
|
959
954
|
windowEnd: z.string(),
|
|
960
955
|
windowStart: z.string()
|
|
961
956
|
}).strict();
|
|
962
|
-
//#endregion
|
|
963
957
|
export { forkConversationBodySchema as A, briefLinkSchema as B, conversationReportEventSchema as C, conversationUsageSchema as D, conversationSummaryReportSchema as E, readMessageAttachments as F, messageCardRef as G, conversationBriefSchema as H, INPUT_IMAGE_TYPES as I, removedCardSchema as J, messageCardText as K, detectImageMediaType as L, conversationChildAgentTotalsSchema as M, MAX_INPUT_IMAGES as N, createConversationBodySchema as O, MAX_INPUT_IMAGE_BYTES as P, isVisionImageMediaType as R, conversationReportEventDataSchema as S, conversationStatsReportSchema as T, parseBriefInput as U, briefOutcomeStatusSchema as V, annotationCard as W, resolveMessageCards as Y, conversationParamsSchema as _, cancelConversationPendingMessagesBodySchema as a, conversationPendingMessageSchema as b, conversationAttachmentParamsSchema as c, conversationDetailReportSchema as d, conversationEventHistorySchema as f, conversationFeedSchema as g, conversationFeedQuerySchema as h, archiveConversationResponseSchema as i, forkConversationResponseSchema as j, createConversationMessageBodySchema as k, conversationAuxiliaryCostsSchema as l, conversationEventsQuerySchema as m, actorIdentitySchema as n, cancelConversationPendingMessagesResponseSchema as o, conversationEventPageSchema as p, readMessageCardRefs as q, archiveConversationBodySchema as r, conversationActivityPreviewSchema as s, acceptedConversationMessageSchema as t, conversationDetailQuerySchema as u, conversationPendingAuthorizationSchema as v, conversationStatsItemSchema as w, conversationPendingMessagesReportSchema as x, conversationPendingMessageDeliverySchema as y, briefCodeChangeSchema as z };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { m as logWarn } from "./logging-DsHONhVm.js";
|
|
2
2
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
3
|
-
|
|
3
|
+
// src/chat/conversation-privacy.ts
|
|
4
4
|
const SAFE_METADATA_KEY_LIMIT = 20;
|
|
5
5
|
const conversationPrivacyStorage = new AsyncLocalStorage();
|
|
6
6
|
/**
|
|
@@ -178,5 +178,4 @@ function toGenAiMessagesTraceAttributes(prefix, messages) {
|
|
|
178
178
|
...partTypes.size > 0 ? { [`${prefix}.part_types`]: [...partTypes] } : void 0
|
|
179
179
|
};
|
|
180
180
|
}
|
|
181
|
-
//#endregion
|
|
182
181
|
export { toCanonicalInputMessage as a, toGenAiPayloadMetadata as c, runWithConversationPrivacy as i, toGenAiPayloadTraceAttributes as l, getCurrentConversationPrivacy as n, toCanonicalOutputMessage as o, resolveConversationPrivacy as r, toGenAiMessagesTraceAttributes as s, canExposeConversationPayload as t };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
// src/chat/local/conversation-work.ts
|
|
2
2
|
/**
|
|
3
3
|
* Run local conversation work in this process and wait for every accepted wake.
|
|
4
4
|
*
|
|
@@ -47,5 +47,4 @@ function createLocalConversationWork(processMessage) {
|
|
|
47
47
|
}
|
|
48
48
|
};
|
|
49
49
|
}
|
|
50
|
-
//#endregion
|
|
51
50
|
export { createLocalConversationWork };
|
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
import { Ft as resolveBaseUrl, Lt as createUserTokenStore, Nt as formatProviderLabel, Pt as parseOAuthStatePayload, _ as resolvePluginOAuthAccount, d as getMcpAuthSession, f as getMcpStoredOAuthCredentials, o as finalizeMcpAuthorization, p as putMcpStoredOAuthCredentials, s as deleteMcpAuthSession, x as lookupSlackUserProfile, xt as getMcpProviderErrorAttributes } from "./agent-runner-
|
|
2
|
-
import { f as escapeXml } from "./client-
|
|
3
|
-
import {
|
|
4
|
-
import { a as getRuntimeMetadata, n as botConfig } from "./config-
|
|
5
|
-
import { f as parseSlackUserId } from "./actor-
|
|
6
|
-
import {
|
|
7
|
-
import { i as homeDir } from "./package-discovery-
|
|
8
|
-
import { n as buildOAuthTokenRequest, r as parseOAuthTokenResponse, u as hasRequiredOAuthScope } from "./registry-
|
|
9
|
-
import { n as pluginCatalogRuntime } from "./catalog-runtime-
|
|
10
|
-
import { t as discoverSkills } from "./skills-
|
|
11
|
-
import {
|
|
12
|
-
import { Ht as getSlackClient } from "./agent-hooks-
|
|
13
|
-
import { E as acquireActiveLock, w as getStateAdapter } from "./profile-
|
|
14
|
-
import { i as getConversationPendingAuth } from "./pending-auth-
|
|
15
|
-
import { r as getPersistedThreadState, s as coerceThreadConversationState } from "./thread-state-
|
|
16
|
-
import { c as deleteWebAuthorization, f as wakeAuthorizedTurn, i as readConnectedOAuthTokens, p as wakePausedTurn } from "./connections-
|
|
17
|
-
import { n as relayLocalOAuthCallback } from "./oauth-relay-
|
|
1
|
+
import { Ft as resolveBaseUrl, Lt as createUserTokenStore, Nt as formatProviderLabel, Pt as parseOAuthStatePayload, _ as resolvePluginOAuthAccount, d as getMcpAuthSession, f as getMcpStoredOAuthCredentials, o as finalizeMcpAuthorization, p as putMcpStoredOAuthCredentials, s as deleteMcpAuthSession, x as lookupSlackUserProfile, xt as getMcpProviderErrorAttributes } from "./agent-runner-DGsFQw72.js";
|
|
2
|
+
import { f as escapeXml } from "./client-DbyHuMFU.js";
|
|
3
|
+
import { L as isNativeIdentityProvider, f as logException, g as runBestEffort, m as logWarn } from "./logging-DsHONhVm.js";
|
|
4
|
+
import { a as getRuntimeMetadata, n as botConfig } from "./config-_WO_AjCB.js";
|
|
5
|
+
import { f as parseSlackUserId } from "./actor-tlxzqaRe.js";
|
|
6
|
+
import { F as upsertIdentity, I as upsertLinkedIdentity, b as identityFromActor, f as getSqlExecutor, j as findUserByVerifiedEmails } from "./viewer-CGvvRqKp.js";
|
|
7
|
+
import { i as homeDir } from "./package-discovery-DJBompdd.js";
|
|
8
|
+
import { n as buildOAuthTokenRequest, r as parseOAuthTokenResponse, u as hasRequiredOAuthScope } from "./registry-Du566MtJ.js";
|
|
9
|
+
import { n as pluginCatalogRuntime } from "./catalog-runtime-BN4DVxco.js";
|
|
10
|
+
import { t as discoverSkills } from "./skills-DyQBLIrK.js";
|
|
11
|
+
import { B as postSlackMessage, Ft as recordAuthenticationLinked, It as recordAuthorizationCompleted, Z as getTurnRecord } from "./tasks-CEXKTASS.js";
|
|
12
|
+
import { Ht as getSlackClient } from "./agent-hooks-BJ_5mlRH.js";
|
|
13
|
+
import { E as acquireActiveLock, w as getStateAdapter } from "./profile-DpYjfKke.js";
|
|
14
|
+
import { i as getConversationPendingAuth } from "./pending-auth-D8J1uJUS.js";
|
|
15
|
+
import { r as getPersistedThreadState, s as coerceThreadConversationState } from "./thread-state-W3f6kAtz.js";
|
|
16
|
+
import { c as deleteWebAuthorization, f as wakeAuthorizedTurn, i as readConnectedOAuthTokens, p as wakePausedTurn } from "./connections-ag_1JOhB.js";
|
|
17
|
+
import { n as relayLocalOAuthCallback } from "./oauth-relay-CTygMkNx.js";
|
|
18
18
|
import path from "node:path";
|
|
19
19
|
import { z } from "zod";
|
|
20
20
|
import { createHmac, createSecretKey, timingSafeEqual } from "node:crypto";
|
|
21
21
|
import { pluginStoredTokensSchema } from "@sentry/junior-plugin-api";
|
|
22
22
|
import fs from "node:fs";
|
|
23
|
-
|
|
23
|
+
// src/handlers/oauth-html.ts
|
|
24
24
|
/** Build pre-escaped callback HTML with the shared response security policy. */
|
|
25
25
|
function htmlCallbackResponse(title, message, status, options = {}) {
|
|
26
26
|
const footerMessage = options.footerMessage ?? `You can close this tab and return to ${botConfig.userName}.`;
|
|
@@ -183,8 +183,7 @@ function htmlCallbackResponse(title, message, status, options = {}) {
|
|
|
183
183
|
}
|
|
184
184
|
});
|
|
185
185
|
}
|
|
186
|
-
|
|
187
|
-
//#region src/handlers/mcp-oauth-callback.ts
|
|
186
|
+
// src/handlers/mcp-oauth-callback.ts
|
|
188
187
|
/**
|
|
189
188
|
* MCP OAuth callback handler.
|
|
190
189
|
*
|
|
@@ -404,8 +403,7 @@ async function GET$1(request, provider, waitUntil, options) {
|
|
|
404
403
|
return htmlResponse("failure");
|
|
405
404
|
}
|
|
406
405
|
}
|
|
407
|
-
|
|
408
|
-
//#region src/chat/slack/app-home.ts
|
|
406
|
+
// src/chat/slack/app-home.ts
|
|
409
407
|
const DEFAULT_DESCRIPTION_TEXT = "I help your team investigate, summarize, and act on work in Slack.";
|
|
410
408
|
const MAX_HOME_SKILLS = 6;
|
|
411
409
|
const MAX_SECTION_TEXT_CHARS = 3e3;
|
|
@@ -536,8 +534,7 @@ async function publishAppHomeView(slackClient, userId, userTokenStore) {
|
|
|
536
534
|
view
|
|
537
535
|
});
|
|
538
536
|
}
|
|
539
|
-
|
|
540
|
-
//#region src/handlers/oauth-callback.ts
|
|
537
|
+
// src/handlers/oauth-callback.ts
|
|
541
538
|
/**
|
|
542
539
|
* OAuth callbacks exchange and store credentials. Public signed callbacks
|
|
543
540
|
* relay to the owning CLI, which controls local continuation. Slack callbacks
|
|
@@ -558,6 +555,57 @@ function oauthTokenErrorAttributes(provider, endpoint, status) {
|
|
|
558
555
|
function pluginAuthorizationId(args) {
|
|
559
556
|
return `${args.sessionId}:plugin:${args.provider}`;
|
|
560
557
|
}
|
|
558
|
+
/** Return the Junior user of the person who started the OAuth connection. */
|
|
559
|
+
async function resolveOAuthActorUserId(actor) {
|
|
560
|
+
if (actor.platform === "web") {
|
|
561
|
+
const observation = identityFromActor(actor.email ? {
|
|
562
|
+
email: actor.email,
|
|
563
|
+
...actor.fullName ? { fullName: actor.fullName } : void 0
|
|
564
|
+
} : void 0);
|
|
565
|
+
return observation ? (await upsertIdentity(getSqlExecutor(), observation)).userId : void 0;
|
|
566
|
+
}
|
|
567
|
+
const slackUserId = parseSlackUserId(actor.userId);
|
|
568
|
+
if (!slackUserId) throw new Error("OAuth Slack actor user id is invalid");
|
|
569
|
+
const profile = await lookupSlackUserProfile(slackUserId);
|
|
570
|
+
return (await upsertIdentity(getSqlExecutor(), {
|
|
571
|
+
kind: "user",
|
|
572
|
+
provider: "slack",
|
|
573
|
+
providerTenantId: actor.teamId,
|
|
574
|
+
providerSubjectId: profile.id,
|
|
575
|
+
displayName: profile.real_name || profile.display_name,
|
|
576
|
+
handle: profile.name,
|
|
577
|
+
...profile.email ? {
|
|
578
|
+
email: profile.email,
|
|
579
|
+
emailVerified: true
|
|
580
|
+
} : void 0
|
|
581
|
+
})).userId;
|
|
582
|
+
}
|
|
583
|
+
/**
|
|
584
|
+
* Link a connected provider account to the person who connected it.
|
|
585
|
+
*
|
|
586
|
+
* The actor's user wins. A provider-verified email that matches exactly one
|
|
587
|
+
* user links the account when the actor has no user, and is saved on the
|
|
588
|
+
* identity when it matches the actor's user.
|
|
589
|
+
*/
|
|
590
|
+
async function linkOAuthAccountIdentity(args) {
|
|
591
|
+
const executor = getSqlExecutor();
|
|
592
|
+
const actorUserId = await resolveOAuthActorUserId(args.actor);
|
|
593
|
+
const emailMatch = await findUserByVerifiedEmails(executor, args.verifiedEmails);
|
|
594
|
+
const userId = actorUserId ?? emailMatch?.userId;
|
|
595
|
+
if (!userId) throw new Error("OAuth account has no Junior user to link");
|
|
596
|
+
const email = emailMatch?.userId === userId ? emailMatch.email : void 0;
|
|
597
|
+
await upsertLinkedIdentity(executor, userId, {
|
|
598
|
+
kind: "user",
|
|
599
|
+
provider: args.provider,
|
|
600
|
+
providerSubjectId: args.account.id,
|
|
601
|
+
displayName: args.account.displayName,
|
|
602
|
+
handle: args.account.handle ?? args.account.label,
|
|
603
|
+
...email ? {
|
|
604
|
+
email,
|
|
605
|
+
emailVerified: true
|
|
606
|
+
} : void 0
|
|
607
|
+
});
|
|
608
|
+
}
|
|
561
609
|
/** Queue the pending Turn, including a newer Turn that reused this auth link. */
|
|
562
610
|
async function wakeAuthorizedPluginTurn(stored, options) {
|
|
563
611
|
if (!stored.resumeConversationId || !stored.resumeSessionId || !stored.destination) return;
|
|
@@ -640,8 +688,9 @@ async function GET(request, provider, waitUntil, options) {
|
|
|
640
688
|
return htmlErrorResponse("Connection failed", "The token exchange with the provider failed. Please try again.", 500);
|
|
641
689
|
}
|
|
642
690
|
let parsedTokenResponse;
|
|
691
|
+
let tokenData;
|
|
643
692
|
try {
|
|
644
|
-
|
|
693
|
+
tokenData = await tokenResponse.json();
|
|
645
694
|
parsedTokenResponse = parseOAuthTokenResponse(tokenData, requestedScope, { treatEmptyScopeAsUnreported: providerConfig.treatEmptyScopeAsUnreported });
|
|
646
695
|
} catch {
|
|
647
696
|
logWarn("oauth.token_exchange.failed", oauthTokenErrorAttributes(provider, providerConfig.tokenEndpoint, tokenResponse.status));
|
|
@@ -650,11 +699,18 @@ async function GET(request, provider, waitUntil, options) {
|
|
|
650
699
|
if (!hasRequiredOAuthScope(parsedTokenResponse.scope, requestedScope)) return htmlErrorResponse("Connection failed", `The ${providerLabel} authorization did not grant the access Junior requires. Return to Junior and connect your ${providerLabel} account again.`, 400);
|
|
651
700
|
const userTokenStore = createUserTokenStore();
|
|
652
701
|
let account;
|
|
702
|
+
let verifiedEmails = [];
|
|
653
703
|
try {
|
|
654
|
-
|
|
704
|
+
const resolved = await resolvePluginOAuthAccount({
|
|
655
705
|
provider,
|
|
706
|
+
tokenResponse: tokenData,
|
|
656
707
|
tokens: parsedTokenResponse
|
|
657
708
|
});
|
|
709
|
+
if (resolved) {
|
|
710
|
+
const { verifiedEmails: emails, ...rest } = resolved;
|
|
711
|
+
account = rest;
|
|
712
|
+
verifiedEmails = emails ?? [];
|
|
713
|
+
}
|
|
658
714
|
} catch {
|
|
659
715
|
return htmlErrorResponse("Connection failed", `Junior could not verify the connected ${providerLabel} account. Please try again.`, 500);
|
|
660
716
|
}
|
|
@@ -662,30 +718,13 @@ async function GET(request, provider, waitUntil, options) {
|
|
|
662
718
|
...parsedTokenResponse,
|
|
663
719
|
...account ? { account } : void 0
|
|
664
720
|
});
|
|
665
|
-
const
|
|
666
|
-
if (account &&
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
const slackIdentity = await upsertIdentity(getSqlExecutor(), {
|
|
671
|
-
kind: "user",
|
|
672
|
-
provider: "slack",
|
|
673
|
-
providerTenantId: slackActor.teamId,
|
|
674
|
-
providerSubjectId: profile.id,
|
|
675
|
-
displayName: profile.real_name || profile.display_name,
|
|
676
|
-
handle: profile.name,
|
|
677
|
-
...profile.email ? {
|
|
678
|
-
email: profile.email,
|
|
679
|
-
emailVerified: true
|
|
680
|
-
} : void 0
|
|
681
|
-
});
|
|
682
|
-
if (!slackIdentity.userId) throw new Error("OAuth Slack identity is not linked to a user");
|
|
683
|
-
await upsertLinkedIdentity(getSqlExecutor(), slackIdentity.userId, {
|
|
684
|
-
kind: "user",
|
|
721
|
+
const linkActor = stored.actor;
|
|
722
|
+
if (account && !isNativeIdentityProvider(provider) && (linkActor?.platform === "slack" || linkActor?.platform === "web")) await runBestEffort(async () => {
|
|
723
|
+
await linkOAuthAccountIdentity({
|
|
724
|
+
account,
|
|
725
|
+
actor: linkActor,
|
|
685
726
|
provider,
|
|
686
|
-
|
|
687
|
-
displayName: account.displayName,
|
|
688
|
-
handle: account.handle ?? account.label
|
|
727
|
+
verifiedEmails
|
|
689
728
|
});
|
|
690
729
|
}, "oauth.callback.identity_link.failed", { "app.credential.provider": provider });
|
|
691
730
|
const resumeConversationId = stored.resumeConversationId;
|
|
@@ -751,8 +790,7 @@ async function GET(request, provider, waitUntil, options) {
|
|
|
751
790
|
const footerMessage = stored.destination?.platform === "local" || resumesWebTurn || webActor ? `You can close this tab and return to ${botName}.` : "You can close this tab and return to Slack.";
|
|
752
791
|
return htmlCallbackResponse(escapeXml(`${providerLabel} account connected`), escapeXml(statusMessage), 200, { footerMessage: escapeXml(footerMessage) });
|
|
753
792
|
}
|
|
754
|
-
|
|
755
|
-
//#region src/chat/local/credential-sync.ts
|
|
793
|
+
// src/chat/local/credential-sync.ts
|
|
756
794
|
const LOCAL_CREDENTIAL_SYNC_CONTEXT = "junior.local-credential-sync.v1";
|
|
757
795
|
const LOCAL_CREDENTIAL_SYNC_MAX_AGE_MS = 6e4;
|
|
758
796
|
const localCredentialSyncSchema = z.object({
|
|
@@ -812,5 +850,4 @@ async function receiveLocalOAuthCredential(request) {
|
|
|
812
850
|
await createUserTokenStore().set("local-cli", payload.data.provider, payload.data.tokens);
|
|
813
851
|
return new Response(null, { status: 204 });
|
|
814
852
|
}
|
|
815
|
-
//#endregion
|
|
816
853
|
export { GET$1 as a, publishAppHomeView as i, syncLocalOAuthCredential as n, GET as r, receiveLocalOAuthCredential as t };
|