@sentry/junior 0.151.0 → 0.153.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.
Files changed (64) hide show
  1. package/dist/{agent-hooks-EYUAEBMA.js → agent-hooks-7BWOB7SN.js} +10 -10
  2. package/dist/api/conversations/list.d.ts +11 -5
  3. package/dist/api/schema/conversation.d.ts +11 -0
  4. package/dist/api/schema.d.ts +1 -1
  5. package/dist/api/schema.js +3 -1
  6. package/dist/api.js +52 -31
  7. package/dist/app.js +38 -38
  8. package/dist/{catalog-runtime-2LCLLOBI.js → catalog-runtime-CGUDNL3D.js} +5 -5
  9. package/dist/chat/api-turns/authorization.d.ts +23 -0
  10. package/dist/{chunk-QVQBWWXQ.js → chunk-2J4VCHRX.js} +6 -6
  11. package/dist/{chunk-J5LAA2LI.js → chunk-2NS3ACHB.js} +45 -11
  12. package/dist/chunk-37LMRT7G.js +89 -0
  13. package/dist/{chunk-JSKTDBSS.js → chunk-4TWLKHOM.js} +4 -4
  14. package/dist/{chunk-ZGSL5ARH.js → chunk-5DMPHA4V.js} +141 -66
  15. package/dist/{chunk-JIJOPRD4.js → chunk-5QBK3QHJ.js} +4 -4
  16. package/dist/{chunk-KPQBQRNM.js → chunk-5TXDKTET.js} +5 -5
  17. package/dist/{chunk-OYRFUQOV.js → chunk-5XBRH3N7.js} +59 -12
  18. package/dist/{chunk-6A46QL4O.js → chunk-A5SROS6H.js} +4 -4
  19. package/dist/{chunk-WVXFEQXE.js → chunk-COC65LIW.js} +1 -1
  20. package/dist/{chunk-6DLWRSGV.js → chunk-EPOA52SD.js} +1 -1
  21. package/dist/{chunk-5N3XLYBW.js → chunk-ET54Q4TD.js} +1 -1
  22. package/dist/{chunk-M6KRPBXC.js → chunk-FLEY546A.js} +6 -6
  23. package/dist/{chunk-OAPPJ3TM.js → chunk-HMU2QP5M.js} +1 -1
  24. package/dist/{chunk-H7ZMEHAN.js → chunk-HOK7MEWG.js} +1 -1
  25. package/dist/{chunk-6PGJPCN2.js → chunk-HYEAR6HL.js} +1 -1
  26. package/dist/{chunk-EMB4VY7H.js → chunk-ISEROVYZ.js} +5 -5
  27. package/dist/{chunk-AGSUPAD5.js → chunk-JAJVUQV7.js} +3 -3
  28. package/dist/{chunk-DJAOSWB6.js → chunk-JJAMURMR.js} +1 -1
  29. package/dist/{chunk-2MGJ64SL.js → chunk-JY2HJYJT.js} +1 -1
  30. package/dist/{chunk-CL5DT6D2.js → chunk-K4LK6KYO.js} +4 -4
  31. package/dist/{chunk-OFRJXFTH.js → chunk-O2YXWWPM.js} +8 -8
  32. package/dist/{chunk-D22FO4LW.js → chunk-PGJBNO3I.js} +2 -2
  33. package/dist/{chunk-6WNWM5JD.js → chunk-PMJAY6JS.js} +5 -5
  34. package/dist/{chunk-C7D2ONB5.js → chunk-RKW5QGGN.js} +1 -1
  35. package/dist/{chunk-UDDCHQN2.js → chunk-TIV3PX5H.js} +1 -1
  36. package/dist/{chunk-XN3QKNQX.js → chunk-UG5UCHHJ.js} +7 -0
  37. package/dist/{chunk-3WOK4ZLX.js → chunk-URFV5RWN.js} +18 -18
  38. package/dist/{chunk-PWMVR2MD.js → chunk-VXWTGOLW.js} +1 -1
  39. package/dist/{chunk-B7KWBJAR.js → chunk-WTKAALLV.js} +6 -6
  40. package/dist/{chunk-K3QXMZDU.js → chunk-XAYXN4EG.js} +3 -3
  41. package/dist/{chunk-YN4W5SRJ.js → chunk-XQPKMLRI.js} +1 -1
  42. package/dist/{chunk-PQUV3NA5.js → chunk-YECBSG77.js} +2 -2
  43. package/dist/cli/chat.js +30 -30
  44. package/dist/cli/check.js +6 -6
  45. package/dist/cli/plugins.js +13 -13
  46. package/dist/cli/snapshot-create.js +9 -9
  47. package/dist/cli/upgrade.js +7 -7
  48. package/dist/{db-ALCBI4JZ.js → db-QNQM5YRR.js} +7 -7
  49. package/dist/handlers/mcp-oauth-callback.d.ts +3 -0
  50. package/dist/handlers/oauth-callback.d.ts +3 -0
  51. package/dist/instrumentation.js +4 -4
  52. package/dist/nitro.js +2 -2
  53. package/dist/{oauth-callback-server-3RRMG62B.js → oauth-callback-server-ERQPIR27.js} +23 -24
  54. package/dist/{runner-V6C3EELU.js → runner-BX46SQIE.js} +14 -16
  55. package/dist/{skills-43PFYZIZ.js → skills-JL44EIRX.js} +6 -6
  56. package/dist/spawn-W6FO32T4.js +38 -0
  57. package/dist/{validation-4MNN6QKE.js → validation-UU2AIJIY.js} +6 -6
  58. package/dist/version.js +1 -1
  59. package/dist/{work-YZO6XTEB.js → work-SS7RU5CH.js} +17 -17
  60. package/dist/{worker-42AR7323.js → worker-5P2E7LVI.js} +11 -11
  61. package/package.json +5 -5
  62. package/dist/chunk-4ABTAQYC.js +0 -48
  63. package/dist/chunk-4CODA7P5.js +0 -43
  64. package/dist/spawn-UZNNTNFU.js +0 -38
@@ -4,30 +4,30 @@ import {
4
4
  isConversationScopedChannel,
5
5
  isDmChannel,
6
6
  normalizeSlackConversationId
7
- } from "./chunk-AGSUPAD5.js";
7
+ } from "./chunk-JAJVUQV7.js";
8
8
  import {
9
9
  getConversationEventStore,
10
10
  getDb
11
- } from "./chunk-K3QXMZDU.js";
11
+ } from "./chunk-XAYXN4EG.js";
12
12
  import {
13
13
  juniorConversationAnnotations,
14
14
  juniorConversationEvents,
15
15
  juniorIdentities,
16
16
  juniorUsers
17
- } from "./chunk-5N3XLYBW.js";
17
+ } from "./chunk-ET54Q4TD.js";
18
18
  import {
19
19
  SANDBOX_WORKSPACE_ROOT
20
20
  } from "./chunk-EM225ITJ.js";
21
21
  import {
22
22
  getStateAdapter
23
- } from "./chunk-YN4W5SRJ.js";
23
+ } from "./chunk-XQPKMLRI.js";
24
24
  import {
25
25
  botConfig,
26
26
  completeObject,
27
27
  embedTexts,
28
28
  getSlackBotToken,
29
29
  standardModelId
30
- } from "./chunk-D22FO4LW.js";
30
+ } from "./chunk-PGJBNO3I.js";
31
31
  import {
32
32
  isActorUserId,
33
33
  parseActorUserId
@@ -42,7 +42,7 @@ import {
42
42
  logInfo,
43
43
  logWarn,
44
44
  normalizeIdentityEmail
45
- } from "./chunk-OAPPJ3TM.js";
45
+ } from "./chunk-HMU2QP5M.js";
46
46
 
47
47
  // src/chat/plugins/agent-hooks.ts
48
48
  import {
@@ -1,7 +1,8 @@
1
1
  import {
2
2
  coerceThreadConversationState,
3
- getPersistedThreadState
4
- } from "./chunk-EMB4VY7H.js";
3
+ getPersistedThreadState,
4
+ persistThreadStateById
5
+ } from "./chunk-ISEROVYZ.js";
5
6
  import {
6
7
  pluginTaskId,
7
8
  pluginTaskParamsSchema,
@@ -17,10 +18,11 @@ import {
17
18
  isToolResultError,
18
19
  isToolResultMessage,
19
20
  markConversationMessage,
21
+ markTurnClosed,
20
22
  markTurnCompleted,
21
23
  normalizeToolNameFromResult,
22
24
  stripRuntimeTurnContext
23
- } from "./chunk-JIJOPRD4.js";
25
+ } from "./chunk-5QBK3QHJ.js";
24
26
  import {
25
27
  JUNIOR_THREAD_STATE_TTL_MS
26
28
  } from "./chunk-3Y47VMHV.js";
@@ -31,25 +33,25 @@ import {
31
33
  createPluginModel,
32
34
  createPluginState,
33
35
  getPlugins
34
- } from "./chunk-QVQBWWXQ.js";
36
+ } from "./chunk-2J4VCHRX.js";
35
37
  import {
36
38
  getConversationStore,
37
39
  getDb,
38
40
  sameActorIdentity
39
- } from "./chunk-K3QXMZDU.js";
41
+ } from "./chunk-XAYXN4EG.js";
40
42
  import {
41
43
  juniorConversations,
42
44
  juniorTaskExecutions
43
- } from "./chunk-5N3XLYBW.js";
45
+ } from "./chunk-ET54Q4TD.js";
44
46
  import {
45
47
  getStateAdapter
46
- } from "./chunk-YN4W5SRJ.js";
48
+ } from "./chunk-XQPKMLRI.js";
47
49
  import {
48
50
  ProviderError,
49
51
  findProviderError,
50
52
  getProviderErrorAttributes,
51
53
  getProviderErrorUserMessage
52
- } from "./chunk-D22FO4LW.js";
54
+ } from "./chunk-PGJBNO3I.js";
53
55
  import {
54
56
  credentialSubjectSchema
55
57
  } from "./chunk-RUIXF3YQ.js";
@@ -59,7 +61,7 @@ import {
59
61
  import {
60
62
  buildTurnFailureResponse,
61
63
  logWarn
62
- } from "./chunk-OAPPJ3TM.js";
64
+ } from "./chunk-HMU2QP5M.js";
63
65
 
64
66
  // src/chat/runtime/delivered-turn-state.ts
65
67
  function buildDeliveredTurnStatePatch(args) {
@@ -85,7 +87,7 @@ import { pluginRunContextSchema } from "@sentry/junior-plugin-api";
85
87
 
86
88
  // src/chat/services/turn-session-routing.ts
87
89
  async function resolveTurnSessionRouting(args) {
88
- const conversationStore = args.conversationStore ?? (await import("./db-ALCBI4JZ.js")).getConversationStore();
90
+ const conversationStore = args.conversationStore ?? (await import("./db-QNQM5YRR.js")).getConversationStore();
89
91
  const conversation = await conversationStore.get({
90
92
  conversationId: args.conversationId
91
93
  });
@@ -1183,6 +1185,36 @@ function getTurnUserReplyAttachmentContext(message) {
1183
1185
  };
1184
1186
  }
1185
1187
 
1188
+ // src/chat/runtime/auth-pause-state.ts
1189
+ function completeAuthPauseTurn(args) {
1190
+ markConversationMessage(
1191
+ args.conversation,
1192
+ getTurnUserMessageId(args.conversation, args.sessionId),
1193
+ {
1194
+ replied: true,
1195
+ skippedReason: void 0
1196
+ }
1197
+ );
1198
+ markTurnClosed({
1199
+ conversation: args.conversation,
1200
+ nowMs: Date.now(),
1201
+ sessionId: args.sessionId
1202
+ });
1203
+ }
1204
+ async function persistAuthPauseTurnState(args) {
1205
+ const currentState = await getPersistedThreadState(args.threadStateId);
1206
+ const conversation = coerceThreadConversationState(currentState);
1207
+ await hydrateConversationMessages({
1208
+ conversation,
1209
+ conversationId: args.threadStateId
1210
+ });
1211
+ completeAuthPauseTurn({
1212
+ conversation,
1213
+ sessionId: args.sessionId
1214
+ });
1215
+ await persistThreadStateById(args.threadStateId, { conversation });
1216
+ }
1217
+
1186
1218
  export {
1187
1219
  recordTaskExecution,
1188
1220
  readTaskExecutionSummaries,
@@ -1218,5 +1250,7 @@ export {
1218
1250
  getInterruptionMarker,
1219
1251
  requireTurnFailureEventId,
1220
1252
  getAgentTurnDiagnosticsAttributes,
1221
- finalizeFailedTurnReplyWithEvent
1253
+ finalizeFailedTurnReplyWithEvent,
1254
+ completeAuthPauseTurn,
1255
+ persistAuthPauseTurnState
1222
1256
  };
@@ -0,0 +1,89 @@
1
+ import {
2
+ getStateAdapter
3
+ } from "./chunk-XQPKMLRI.js";
4
+ import {
5
+ getClient
6
+ } from "./chunk-6GWA276C.js";
7
+
8
+ // src/chat/api-turns/authorization.ts
9
+ import { randomUUID } from "crypto";
10
+ var WEB_AUTHORIZATION_PREFIX = "junior:web_authorization:v1";
11
+ var WEB_AUTHORIZATION_TTL_MS = 24 * 60 * 60 * 1e3;
12
+ function authorizationKey(conversationId, actorId) {
13
+ return `${WEB_AUTHORIZATION_PREFIX}:${conversationId}:${actorId}`;
14
+ }
15
+ function createWebAuthorization(args) {
16
+ return {
17
+ createState: async () => randomUUID(),
18
+ deliver: async (request) => {
19
+ await getStateAdapter().set(
20
+ authorizationKey(args.conversationId, args.actorId),
21
+ JSON.stringify({ ...request, ...args }),
22
+ WEB_AUTHORIZATION_TTL_MS
23
+ );
24
+ }
25
+ };
26
+ }
27
+ async function getWebAuthorization(args) {
28
+ const value = await getStateAdapter().get(
29
+ authorizationKey(args.conversationId, args.actorId)
30
+ );
31
+ if (typeof value !== "string") return void 0;
32
+ try {
33
+ const parsed = JSON.parse(value);
34
+ if (parsed.actorId !== args.actorId || parsed.conversationId !== args.conversationId || typeof parsed.authorizationUrl !== "string" || typeof parsed.label !== "string" || typeof parsed.completionText !== "string") {
35
+ return void 0;
36
+ }
37
+ return parsed;
38
+ } catch {
39
+ return void 0;
40
+ }
41
+ }
42
+ async function deleteWebAuthorization(args) {
43
+ await getStateAdapter().delete(
44
+ authorizationKey(args.conversationId, args.actorId)
45
+ );
46
+ }
47
+
48
+ // src/chat/sentry-links.ts
49
+ function getSentryOrgSlug() {
50
+ const slug = process.env.SENTRY_ORG_SLUG?.trim();
51
+ return slug || void 0;
52
+ }
53
+ function isSentrySaasDsnHost(host) {
54
+ return host === "sentry.io" || host.endsWith(".sentry.io");
55
+ }
56
+ function buildSentryWebBaseUrl(dsn) {
57
+ if (isSentrySaasDsnHost(dsn.host)) {
58
+ return "https://sentry.io";
59
+ }
60
+ const port = dsn.port ? `:${dsn.port}` : "";
61
+ const path = dsn.path ? `/${dsn.path}` : "";
62
+ return `${dsn.protocol}://${dsn.host}${port}${path}`;
63
+ }
64
+ function buildSentryConversationUrl(conversationId) {
65
+ const client = getClient();
66
+ const dsn = client?.getDsn();
67
+ if (!dsn?.host || !dsn.projectId) {
68
+ return void 0;
69
+ }
70
+ const orgSlug = getSentryOrgSlug();
71
+ if (!orgSlug) {
72
+ return void 0;
73
+ }
74
+ const encodedId = encodeURIComponent(conversationId);
75
+ const params = new URLSearchParams();
76
+ params.set("project", dsn.projectId);
77
+ const path = `explore/conversations/${encodedId}/?${params.toString()}`;
78
+ if (isSentrySaasDsnHost(dsn.host)) {
79
+ return `https://${orgSlug}.sentry.io/${path}`;
80
+ }
81
+ return `${buildSentryWebBaseUrl(dsn)}/organizations/${orgSlug}/${path}`;
82
+ }
83
+
84
+ export {
85
+ buildSentryConversationUrl,
86
+ createWebAuthorization,
87
+ getWebAuthorization,
88
+ deleteWebAuthorization
89
+ };
@@ -4,18 +4,18 @@ import {
4
4
  } from "./chunk-EM225ITJ.js";
5
5
  import {
6
6
  getStateAdapter
7
- } from "./chunk-YN4W5SRJ.js";
7
+ } from "./chunk-XQPKMLRI.js";
8
8
  import {
9
9
  toOptionalTrimmed
10
- } from "./chunk-D22FO4LW.js";
10
+ } from "./chunk-PGJBNO3I.js";
11
11
  import {
12
12
  pluginCatalogRuntime
13
- } from "./chunk-6DLWRSGV.js";
13
+ } from "./chunk-EPOA52SD.js";
14
14
  import {
15
15
  setSpanAttributes,
16
16
  setSpanStatus,
17
17
  withSpan
18
- } from "./chunk-OAPPJ3TM.js";
18
+ } from "./chunk-HMU2QP5M.js";
19
19
 
20
20
  // src/chat/sandbox/resources.ts
21
21
  var configuredResources;
@@ -3,17 +3,15 @@ import {
3
3
  } from "./chunk-FA6POGLH.js";
4
4
  import {
5
5
  getTurnRequestDeadline
6
- } from "./chunk-H7ZMEHAN.js";
6
+ } from "./chunk-HOK7MEWG.js";
7
7
  import {
8
- persistAuthPauseTurnState
9
- } from "./chunk-4ABTAQYC.js";
10
- import {
11
- buildSentryConversationUrl
12
- } from "./chunk-4CODA7P5.js";
8
+ buildSentryConversationUrl,
9
+ deleteWebAuthorization
10
+ } from "./chunk-37LMRT7G.js";
13
11
  import {
14
12
  ensureConversationWake,
15
13
  requestConversationWork
16
- } from "./chunk-6A46QL4O.js";
14
+ } from "./chunk-A5SROS6H.js";
17
15
  import {
18
16
  buildDeliveredTurnStatePatch,
19
17
  finalizeFailedTurnReplyWithEvent,
@@ -22,10 +20,11 @@ import {
22
20
  getTurnUserMessageId,
23
21
  getTurnUserReplyAttachmentContext,
24
22
  getTurnUserSlackMessageTs,
23
+ persistAuthPauseTurnState,
25
24
  requireTurnFailureEventId,
26
25
  resolveTurnSessionRouting,
27
26
  scheduleSessionCompletedPluginTasks
28
- } from "./chunk-J5LAA2LI.js";
27
+ } from "./chunk-2NS3ACHB.js";
29
28
  import {
30
29
  ConversationTurnLifecycleService,
31
30
  coerceThreadConversationState,
@@ -34,7 +33,7 @@ import {
34
33
  getPersistedSandboxState,
35
34
  getPersistedThreadState,
36
35
  persistThreadStateById
37
- } from "./chunk-EMB4VY7H.js";
36
+ } from "./chunk-ISEROVYZ.js";
38
37
  import {
39
38
  getVercelConversationWorkQueue
40
39
  } from "./chunk-WR76IVA5.js";
@@ -47,7 +46,7 @@ import {
47
46
  getMcpStoredOAuthCredentials,
48
47
  lookupSlackUserProfile,
49
48
  resolvePluginOAuthAccount
50
- } from "./chunk-OFRJXFTH.js";
49
+ } from "./chunk-O2YXWWPM.js";
51
50
  import {
52
51
  RetryableDeliveryError
53
52
  } from "./chunk-RF6J3DIO.js";
@@ -63,13 +62,13 @@ import {
63
62
  removeReactionFromMessage,
64
63
  resolveBaseUrl,
65
64
  truncateStatusText
66
- } from "./chunk-M6KRPBXC.js";
65
+ } from "./chunk-FLEY546A.js";
67
66
  import {
68
67
  parseSlackThreadId,
69
68
  readSlackRawMessageContext,
70
69
  resolveSlackChannelIdFromMessage,
71
70
  resolveSlackChannelIdFromThreadId
72
- } from "./chunk-UDDCHQN2.js";
71
+ } from "./chunk-TIV3PX5H.js";
73
72
  import {
74
73
  CooperativeTurnYieldError,
75
74
  TurnSliceLimitExceededError,
@@ -96,29 +95,29 @@ import {
96
95
  recordTurnSummary,
97
96
  saveTurnCheckpoint,
98
97
  turnHasReply
99
- } from "./chunk-JIJOPRD4.js";
98
+ } from "./chunk-5QBK3QHJ.js";
100
99
  import {
101
100
  getDashboardConversationLink,
102
101
  getPluginSlackConversationLink
103
- } from "./chunk-QVQBWWXQ.js";
102
+ } from "./chunk-2J4VCHRX.js";
104
103
  import {
105
104
  SlackActionError,
106
105
  getHeaderString,
107
106
  getSlackClient,
108
107
  isDmChannel,
109
108
  normalizeSlackConversationId
110
- } from "./chunk-AGSUPAD5.js";
109
+ } from "./chunk-JAJVUQV7.js";
111
110
  import {
112
111
  getConversationEventStore,
113
112
  getSqlExecutor,
114
113
  requireSlackDestination,
115
114
  upsertIdentity,
116
115
  upsertLinkedIdentity
117
- } from "./chunk-K3QXMZDU.js";
116
+ } from "./chunk-XAYXN4EG.js";
118
117
  import {
119
118
  acquireActiveLock,
120
119
  getStateAdapter
121
- } from "./chunk-YN4W5SRJ.js";
120
+ } from "./chunk-XQPKMLRI.js";
122
121
  import {
123
122
  botConfig,
124
123
  escapeXml,
@@ -126,18 +125,18 @@ import {
126
125
  getRuntimeMetadata,
127
126
  normalizeSlackEmojiName,
128
127
  standardModelId
129
- } from "./chunk-D22FO4LW.js";
128
+ } from "./chunk-PGJBNO3I.js";
130
129
  import {
131
130
  discoverSkills
132
- } from "./chunk-PQUV3NA5.js";
131
+ } from "./chunk-YECBSG77.js";
133
132
  import {
134
133
  pluginCatalogRuntime
135
- } from "./chunk-6DLWRSGV.js";
134
+ } from "./chunk-EPOA52SD.js";
136
135
  import {
137
136
  buildOAuthTokenRequest,
138
137
  hasRequiredOAuthScope,
139
138
  parseOAuthTokenResponse
140
- } from "./chunk-2MGJ64SL.js";
139
+ } from "./chunk-JY2HJYJT.js";
141
140
  import {
142
141
  createSlackResumeActor,
143
142
  isUserActor
@@ -155,7 +154,7 @@ import {
155
154
  setTags,
156
155
  toOptionalString,
157
156
  withLogContext
158
- } from "./chunk-OAPPJ3TM.js";
157
+ } from "./chunk-HMU2QP5M.js";
159
158
  import {
160
159
  homeDir
161
160
  } from "./chunk-H4HBKISO.js";
@@ -1814,7 +1813,7 @@ async function wakePausedTurn(request, options = {}) {
1814
1813
 
1815
1814
  // src/handlers/oauth-html.ts
1816
1815
  function htmlCallbackResponse(title, message, status, options = {}) {
1817
- const footerMessage = options.footerMessage ?? "You can close this tab and return to Junior.";
1816
+ const footerMessage = options.footerMessage ?? `You can close this tab and return to ${botConfig.userName}.`;
1818
1817
  const html = `<!DOCTYPE html>
1819
1818
  <html>
1820
1819
  <head><title>${title}</title></head>
@@ -1839,38 +1838,40 @@ function htmlCallbackResponse(title, message, status, options = {}) {
1839
1838
  }
1840
1839
 
1841
1840
  // src/handlers/mcp-oauth-callback.ts
1842
- var CALLBACK_PAGES = {
1843
- missing_state: {
1844
- title: "Authorization failed",
1845
- message: "Missing state parameter.",
1846
- status: 400
1847
- },
1848
- provider_error: {
1849
- title: "Authorization failed",
1850
- message: "The provider returned an authorization error.",
1851
- status: 400
1852
- },
1853
- missing_code: {
1854
- title: "Authorization failed",
1855
- message: "Missing code parameter.",
1856
- status: 400
1857
- },
1858
- expired: {
1859
- title: "Authorization expired",
1860
- message: "This authorization link is no longer active. Return to Junior and retry the original request.",
1861
- status: 400
1862
- },
1863
- success: {
1864
- title: "Authorization complete",
1865
- message: "Your MCP access is connected. Junior will continue the paused request in Slack.",
1866
- status: 200
1867
- },
1868
- failure: {
1869
- title: "Authorization failed",
1870
- message: "Junior could not finish the authorization callback. Return to Junior and retry the original request.",
1871
- status: 500
1872
- }
1873
- };
1841
+ function callbackPages(botName) {
1842
+ return {
1843
+ missing_state: {
1844
+ title: "Authorization failed",
1845
+ message: "Missing state parameter.",
1846
+ status: 400
1847
+ },
1848
+ provider_error: {
1849
+ title: "Authorization failed",
1850
+ message: "The provider returned an authorization error.",
1851
+ status: 400
1852
+ },
1853
+ missing_code: {
1854
+ title: "Authorization failed",
1855
+ message: "Missing code parameter.",
1856
+ status: 400
1857
+ },
1858
+ expired: {
1859
+ title: "Authorization expired",
1860
+ message: `This authorization link is no longer active. Return to ${botName} and retry the original request.`,
1861
+ status: 400
1862
+ },
1863
+ success: {
1864
+ title: "Authorization complete",
1865
+ message: `Your MCP access is connected. ${botName} will continue the paused request.`,
1866
+ status: 200
1867
+ },
1868
+ failure: {
1869
+ title: "Authorization failed",
1870
+ message: `${botName} could not finish the authorization callback. Return to ${botName} and retry the original request.`,
1871
+ status: 500
1872
+ }
1873
+ };
1874
+ }
1874
1875
  var McpOAuthAttemptExpiredError = class extends Error {
1875
1876
  constructor() {
1876
1877
  super("MCP OAuth authorization attempt is no longer current");
@@ -1881,11 +1882,13 @@ function mcpAuthorizationId(args) {
1881
1882
  return `${args.sessionId}:mcp:${args.provider}`;
1882
1883
  }
1883
1884
  function htmlResponse(kind, options) {
1885
+ const botName = botConfig.userName;
1886
+ const pages = callbackPages(botName);
1884
1887
  const page = kind === "success" && options?.local ? {
1885
- ...CALLBACK_PAGES.success,
1886
- message: "Your MCP access is connected. Junior will continue the paused request in the local client."
1887
- } : CALLBACK_PAGES[kind];
1888
- const footerMessage = kind === "success" && !options?.local ? "You can close this tab and return to Slack." : void 0;
1888
+ ...pages.success,
1889
+ message: `Your MCP access is connected. ${botName} will continue the paused request in the local client.`
1890
+ } : pages[kind];
1891
+ const footerMessage = kind === "success" && !options?.local ? `You can close this tab and return to ${botName}.` : void 0;
1889
1892
  return htmlCallbackResponse(page.title, page.message, page.status, {
1890
1893
  footerMessage
1891
1894
  });
@@ -2195,7 +2198,7 @@ async function isCurrentMcpAuthorizationAttempt(authSession, provider) {
2195
2198
  return pendingAuth?.authSessionId === authSession.authSessionId && pendingAuth.sessionId === authSession.sessionId;
2196
2199
  }
2197
2200
  function mcpConversationId(authSession) {
2198
- if (authSession.destination?.platform === "local") {
2201
+ if (authSession.destination?.platform === "local" || authSession.source?.platform === "web") {
2199
2202
  return authSession.conversationId;
2200
2203
  }
2201
2204
  if (authSession.channelId && authSession.threadTs) {
@@ -2291,7 +2294,40 @@ async function GET(request, provider, waitUntil, options) {
2291
2294
  "app.credential.provider": provider
2292
2295
  });
2293
2296
  }
2294
- if (authSession.destination?.platform !== "local") {
2297
+ if (authSession.source?.platform === "web" && authSession.destination) {
2298
+ waitUntil(async () => {
2299
+ const turn = await getTurnRecord(
2300
+ authSession.conversationId,
2301
+ authSession.sessionId
2302
+ );
2303
+ await deleteWebAuthorization({
2304
+ actorId: authSession.userId,
2305
+ conversationId: authSession.conversationId
2306
+ });
2307
+ if (!turn || turn.state !== "paused" || turn.resumeReason !== "auth") {
2308
+ return;
2309
+ }
2310
+ await recordAuthorizationCompleted({
2311
+ conversationId: authSession.conversationId,
2312
+ kind: "mcp",
2313
+ provider,
2314
+ actorId: authSession.userId,
2315
+ authorizationId: mcpAuthorizationId({
2316
+ provider,
2317
+ sessionId: authSession.sessionId
2318
+ })
2319
+ });
2320
+ await wakePausedTurn(
2321
+ {
2322
+ conversationId: authSession.conversationId,
2323
+ destination: authSession.destination,
2324
+ turnId: authSession.sessionId,
2325
+ expectedVersion: turn.version
2326
+ },
2327
+ options.conversationWorkQueue ? { queue: options.conversationWorkQueue } : void 0
2328
+ );
2329
+ });
2330
+ } else if (authSession.destination?.platform !== "local") {
2295
2331
  waitUntil(
2296
2332
  () => resumeAuthorizedMcpTurn({
2297
2333
  authSession,
@@ -2301,7 +2337,9 @@ async function GET(request, provider, waitUntil, options) {
2301
2337
  );
2302
2338
  }
2303
2339
  return htmlResponse("success", {
2304
- local: authSession.destination?.platform === "local"
2340
+ // Web roots keep a local destination for conversation-only delivery.
2341
+ // Only the CLI path should get the local-client success copy.
2342
+ local: authSession.destination?.platform === "local" && authSession.source?.platform !== "web"
2305
2343
  });
2306
2344
  } catch (callbackError) {
2307
2345
  if (callbackError instanceof McpOAuthAttemptExpiredError) {
@@ -3026,7 +3064,7 @@ async function GET2(request, provider, waitUntil, options) {
3026
3064
  { "app.credential.provider": provider }
3027
3065
  );
3028
3066
  }
3029
- if (stored.destination?.platform !== "local") {
3067
+ if (stored.destination?.platform !== "local" && stored.source?.platform !== "web") {
3030
3068
  waitUntil(async () => {
3031
3069
  try {
3032
3070
  await publishAppHomeView(
@@ -3038,10 +3076,46 @@ async function GET2(request, provider, waitUntil, options) {
3038
3076
  }
3039
3077
  });
3040
3078
  }
3079
+ const resumesWebTurn = Boolean(
3080
+ stored.source?.platform === "web" && stored.destination && stored.resumeConversationId && stored.resumeSessionId
3081
+ );
3041
3082
  const resumesAgentTurn = Boolean(
3042
3083
  stored.destination?.platform !== "local" && stored.resumeConversationId && stored.resumeSessionId
3043
3084
  );
3044
- if (resumesAgentTurn) {
3085
+ if (resumesWebTurn) {
3086
+ waitUntil(async () => {
3087
+ const turn = await getTurnRecord(
3088
+ stored.resumeConversationId,
3089
+ stored.resumeSessionId
3090
+ );
3091
+ await deleteWebAuthorization({
3092
+ actorId: stored.userId,
3093
+ conversationId: stored.resumeConversationId
3094
+ });
3095
+ if (!turn || turn.state !== "paused" || turn.resumeReason !== "auth") {
3096
+ return;
3097
+ }
3098
+ await recordAuthorizationCompleted({
3099
+ conversationId: stored.resumeConversationId,
3100
+ kind: "plugin",
3101
+ provider: stored.provider,
3102
+ actorId: stored.userId,
3103
+ authorizationId: pluginAuthorizationId({
3104
+ provider: stored.provider,
3105
+ sessionId: stored.resumeSessionId
3106
+ })
3107
+ });
3108
+ await wakePausedTurn(
3109
+ {
3110
+ conversationId: stored.resumeConversationId,
3111
+ destination: stored.destination,
3112
+ turnId: stored.resumeSessionId,
3113
+ expectedVersion: turn.version
3114
+ },
3115
+ options.conversationWorkQueue ? { queue: options.conversationWorkQueue } : void 0
3116
+ );
3117
+ });
3118
+ } else if (resumesAgentTurn) {
3045
3119
  waitUntil(
3046
3120
  () => withLogContext(
3047
3121
  { conversationId: stored.resumeConversationId },
@@ -3073,8 +3147,9 @@ async function GET2(request, provider, waitUntil, options) {
3073
3147
  })
3074
3148
  );
3075
3149
  }
3076
- const statusMessage = stored.destination?.platform === "local" ? "Your request is continuing in the local Junior client." : resumesAgentTurn ? "Your request is being processed in Slack." : `Your ${providerLabel} account is connected.`;
3077
- const footerMessage = stored.destination?.platform === "local" ? "You can close this tab and return to Junior." : "You can close this tab and return to Slack.";
3150
+ const botName = botConfig.userName;
3151
+ const statusMessage = stored.destination?.platform === "local" && !resumesWebTurn ? `Your request is continuing in the local ${botName} client.` : resumesWebTurn ? `Your request is continuing in ${botName}.` : resumesAgentTurn ? "Your request is being processed in Slack." : `Your ${providerLabel} account is connected.`;
3152
+ const footerMessage = stored.destination?.platform === "local" || resumesWebTurn ? `You can close this tab and return to ${botName}.` : "You can close this tab and return to Slack.";
3078
3153
  return htmlCallbackResponse(
3079
3154
  escapeXml(`${providerLabel} account connected`),
3080
3155
  escapeXml(statusMessage),
@@ -13,7 +13,7 @@ import {
13
13
  instructionProvenanceFor,
14
14
  sanitizePostgresJson,
15
15
  withConversationEventLock
16
- } from "./chunk-K3QXMZDU.js";
16
+ } from "./chunk-XAYXN4EG.js";
17
17
  import {
18
18
  SANDBOX_WORKSPACE_ROOT,
19
19
  sleep
@@ -23,14 +23,14 @@ import {
23
23
  fenceLock,
24
24
  getStateAdapter,
25
25
  withLock
26
- } from "./chunk-YN4W5SRJ.js";
26
+ } from "./chunk-XQPKMLRI.js";
27
27
  import {
28
28
  botConfig,
29
29
  completeText,
30
30
  escapeXml,
31
31
  resolveGatewayModel,
32
32
  unwrapCurrentInstruction
33
- } from "./chunk-D22FO4LW.js";
33
+ } from "./chunk-PGJBNO3I.js";
34
34
  import {
35
35
  toStoredSlackActor
36
36
  } from "./chunk-HZF5P5UN.js";
@@ -42,7 +42,7 @@ import {
42
42
  logException,
43
43
  logWarn,
44
44
  setSpanAttributes
45
- } from "./chunk-OAPPJ3TM.js";
45
+ } from "./chunk-HMU2QP5M.js";
46
46
 
47
47
  // src/chat/turn-context-tag.ts
48
48
  var TURN_CONTEXT_TAG = "runtime-turn-context";