@sentry/junior 0.150.1 → 0.152.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 (77) hide show
  1. package/dist/{agent-hooks-G4LEACQB.js → agent-hooks-U66Q3X2P.js} +10 -10
  2. package/dist/api/schema/conversation.d.ts +35 -4
  3. package/dist/api/schema.d.ts +1 -1
  4. package/dist/api/schema.js +3 -1
  5. package/dist/api.js +81 -38
  6. package/dist/app.js +129 -206
  7. package/dist/{catalog-runtime-ZRSNE2MH.js → catalog-runtime-CVCR7SND.js} +5 -5
  8. package/dist/chat/agent/skills.d.ts +5 -4
  9. package/dist/chat/agent/tools.d.ts +5 -5
  10. package/dist/chat/api-turns/authorization.d.ts +23 -0
  11. package/dist/chat/conversations/history.d.ts +12 -3
  12. package/dist/chat/conversations/projection.d.ts +7 -3
  13. package/dist/chat/mcp/tool-manager.d.ts +0 -4
  14. package/dist/chat/runtime/agent-run-outcome.d.ts +4 -0
  15. package/dist/chat/tools/search-conversation-events.d.ts +1 -1
  16. package/dist/chat/tools/skill/call-mcp-tool.d.ts +0 -1
  17. package/dist/chat/tools/skill/load-skill.d.ts +2 -5
  18. package/dist/chat/tools/types.d.ts +1 -2
  19. package/dist/{chunk-2AWDPNP7.js → chunk-3PCKG4BT.js} +16 -10
  20. package/dist/{chunk-2Z7YX5PI.js → chunk-3UJ3QYRV.js} +156 -19
  21. package/dist/{chunk-IQW6RFXG.js → chunk-5LDOQV7Y.js} +72 -218
  22. package/dist/{chunk-JBYWR6FW.js → chunk-67VR4BJK.js} +5 -5
  23. package/dist/{chunk-5NOHC2Z4.js → chunk-732P2RBQ.js} +1 -1
  24. package/dist/{chunk-3WIFZBJL.js → chunk-7TZM33YX.js} +1 -1
  25. package/dist/{chunk-JVOLC6JZ.js → chunk-AYPU5T5L.js} +4 -4
  26. package/dist/{chunk-TZRYLW3R.js → chunk-CLX3T7Q3.js} +1 -1
  27. package/dist/{chunk-JUBPTYNO.js → chunk-ELAVLP7Z.js} +1 -1
  28. package/dist/{chunk-LSI3EKZQ.js → chunk-ETXLHT3S.js} +4 -4
  29. package/dist/{chunk-N6QJAPZS.js → chunk-I4LR7MS2.js} +45 -11
  30. package/dist/{chunk-6ZYGORV4.js → chunk-KC47ZY6Q.js} +2 -2
  31. package/dist/{chunk-6A24WEKX.js → chunk-KC5XZBRB.js} +4 -4
  32. package/dist/{chunk-D2PVJU5E.js → chunk-KTYC3GDO.js} +3 -3
  33. package/dist/{chunk-AD6N2KNE.js → chunk-KW2MGCW5.js} +5 -5
  34. package/dist/{chunk-QO3OSJDS.js → chunk-LETPYIDF.js} +1 -1
  35. package/dist/{chunk-6IWDFUXW.js → chunk-M6PWM3OK.js} +1 -1
  36. package/dist/{chunk-LWFHRWJI.js → chunk-N2472SQK.js} +8 -8
  37. package/dist/{chunk-QNSV46AW.js → chunk-NF733C66.js} +6 -6
  38. package/dist/{chunk-FGP5W3NS.js → chunk-OEECXAGT.js} +2 -2
  39. package/dist/{chunk-SZ74ECCC.js → chunk-QKPIW2CY.js} +6 -6
  40. package/dist/{chunk-4JV7GUUH.js → chunk-RCBAXKMB.js} +1 -1
  41. package/dist/{chunk-QZGYKKH6.js → chunk-SDMVFTH4.js} +173 -70
  42. package/dist/chunk-SFYDSI34.js +89 -0
  43. package/dist/{chunk-W3FQZAX5.js → chunk-TSQMITMQ.js} +6 -6
  44. package/dist/{chunk-IZE2EGCX.js → chunk-UFKSILED.js} +5 -5
  45. package/dist/{chunk-3JVUWLR7.js → chunk-UG5UCHHJ.js} +15 -1
  46. package/dist/{chunk-OWLJZ6I7.js → chunk-VD6CRYCT.js} +1 -1
  47. package/dist/{chunk-2DIRU2C2.js → chunk-WZN4RQ64.js} +1 -1
  48. package/dist/{chunk-KFHJQYKQ.js → chunk-X4RM4TBW.js} +1 -1
  49. package/dist/{chunk-B2YA2G26.js → chunk-X6JP6AMX.js} +1 -1
  50. package/dist/{chunk-GZ25ZSTX.js → chunk-XTLF7C4I.js} +11 -4
  51. package/dist/{chunk-R53UTQ2Q.js → chunk-Z5WLTGME.js} +1 -1
  52. package/dist/cli/chat.js +30 -30
  53. package/dist/cli/check.js +6 -6
  54. package/dist/cli/plugins.js +13 -13
  55. package/dist/cli/snapshot-create.js +9 -9
  56. package/dist/cli/upgrade.js +7 -7
  57. package/dist/{db-WRA5ZHYE.js → db-HQAZQASY.js} +7 -7
  58. package/dist/handlers/mcp-oauth-callback.d.ts +3 -0
  59. package/dist/handlers/oauth-callback.d.ts +3 -0
  60. package/dist/instrumentation.js +4 -4
  61. package/dist/nitro.js +2 -2
  62. package/dist/{oauth-callback-server-QWAYG3MI.js → oauth-callback-server-OJONZ7T3.js} +23 -24
  63. package/dist/{runner-5JQ54J6P.js → runner-BIJAVQDX.js} +14 -16
  64. package/dist/{skills-3YD55WPO.js → skills-SIPNY4AT.js} +6 -6
  65. package/dist/spawn-ABDIBQT6.js +38 -0
  66. package/dist/{validation-ZXE3IRSB.js → validation-KRPOY5RQ.js} +6 -6
  67. package/dist/version.js +1 -1
  68. package/dist/{work-7G2U64WI.js → work-KS3JOEI2.js} +17 -17
  69. package/dist/{worker-HJM2FZNI.js → worker-CZ5KNZUI.js} +11 -11
  70. package/migrations/0025_mcp_credential_subject.sql +8 -0
  71. package/migrations/meta/0025_snapshot.json +2275 -0
  72. package/migrations/meta/_journal.json +7 -0
  73. package/package.json +5 -5
  74. package/dist/chat/pi/derived-state.d.ts +0 -5
  75. package/dist/chunk-4CODA7P5.js +0 -43
  76. package/dist/chunk-XED3H34M.js +0 -48
  77. package/dist/spawn-OOO26XDL.js +0 -38
@@ -3,17 +3,15 @@ import {
3
3
  } from "./chunk-FA6POGLH.js";
4
4
  import {
5
5
  getTurnRequestDeadline
6
- } from "./chunk-R53UTQ2Q.js";
6
+ } from "./chunk-Z5WLTGME.js";
7
7
  import {
8
- persistAuthPauseTurnState
9
- } from "./chunk-XED3H34M.js";
10
- import {
11
- buildSentryConversationUrl
12
- } from "./chunk-4CODA7P5.js";
8
+ buildSentryConversationUrl,
9
+ deleteWebAuthorization
10
+ } from "./chunk-SFYDSI34.js";
13
11
  import {
14
12
  ensureConversationWake,
15
13
  requestConversationWork
16
- } from "./chunk-JVOLC6JZ.js";
14
+ } from "./chunk-AYPU5T5L.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-N6QJAPZS.js";
27
+ } from "./chunk-I4LR7MS2.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-JBYWR6FW.js";
36
+ } from "./chunk-67VR4BJK.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-LWFHRWJI.js";
49
+ } from "./chunk-N2472SQK.js";
51
50
  import {
52
51
  RetryableDeliveryError
53
52
  } from "./chunk-RF6J3DIO.js";
@@ -63,14 +62,15 @@ import {
63
62
  removeReactionFromMessage,
64
63
  resolveBaseUrl,
65
64
  truncateStatusText
66
- } from "./chunk-SZ74ECCC.js";
65
+ } from "./chunk-QKPIW2CY.js";
67
66
  import {
68
67
  parseSlackThreadId,
69
68
  readSlackRawMessageContext,
70
69
  resolveSlackChannelIdFromMessage,
71
70
  resolveSlackChannelIdFromThreadId
72
- } from "./chunk-4JV7GUUH.js";
71
+ } from "./chunk-RCBAXKMB.js";
73
72
  import {
73
+ CooperativeTurnYieldError,
74
74
  TurnSliceLimitExceededError,
75
75
  abandonTurnRecord,
76
76
  buildConversationContext,
@@ -82,6 +82,7 @@ import {
82
82
  getConversationPendingAuth,
83
83
  getTurnRecord,
84
84
  hydrateConversationMessages,
85
+ isCooperativeTurnYieldError,
85
86
  isPendingAuthLatestRequest,
86
87
  loadProjection,
87
88
  loadTurnCheckpoint,
@@ -94,29 +95,29 @@ import {
94
95
  recordTurnSummary,
95
96
  saveTurnCheckpoint,
96
97
  turnHasReply
97
- } from "./chunk-2AWDPNP7.js";
98
+ } from "./chunk-3PCKG4BT.js";
98
99
  import {
99
100
  getDashboardConversationLink,
100
101
  getPluginSlackConversationLink
101
- } from "./chunk-QNSV46AW.js";
102
+ } from "./chunk-NF733C66.js";
102
103
  import {
103
104
  SlackActionError,
104
105
  getHeaderString,
105
106
  getSlackClient,
106
107
  isDmChannel,
107
108
  normalizeSlackConversationId
108
- } from "./chunk-D2PVJU5E.js";
109
+ } from "./chunk-KTYC3GDO.js";
109
110
  import {
110
111
  getConversationEventStore,
111
112
  getSqlExecutor,
112
113
  requireSlackDestination,
113
114
  upsertIdentity,
114
115
  upsertLinkedIdentity
115
- } from "./chunk-GZ25ZSTX.js";
116
+ } from "./chunk-XTLF7C4I.js";
116
117
  import {
117
118
  acquireActiveLock,
118
119
  getStateAdapter
119
- } from "./chunk-B2YA2G26.js";
120
+ } from "./chunk-X6JP6AMX.js";
120
121
  import {
121
122
  botConfig,
122
123
  escapeXml,
@@ -124,18 +125,18 @@ import {
124
125
  getRuntimeMetadata,
125
126
  normalizeSlackEmojiName,
126
127
  standardModelId
127
- } from "./chunk-FGP5W3NS.js";
128
+ } from "./chunk-OEECXAGT.js";
128
129
  import {
129
130
  discoverSkills
130
- } from "./chunk-6ZYGORV4.js";
131
+ } from "./chunk-KC47ZY6Q.js";
131
132
  import {
132
133
  pluginCatalogRuntime
133
- } from "./chunk-2DIRU2C2.js";
134
+ } from "./chunk-WZN4RQ64.js";
134
135
  import {
135
136
  buildOAuthTokenRequest,
136
137
  hasRequiredOAuthScope,
137
138
  parseOAuthTokenResponse
138
- } from "./chunk-TZRYLW3R.js";
139
+ } from "./chunk-CLX3T7Q3.js";
139
140
  import {
140
141
  createSlackResumeActor,
141
142
  isUserActor
@@ -153,7 +154,7 @@ import {
153
154
  setTags,
154
155
  toOptionalString,
155
156
  withLogContext
156
- } from "./chunk-3WIFZBJL.js";
157
+ } from "./chunk-7TZM33YX.js";
157
158
  import {
158
159
  homeDir
159
160
  } from "./chunk-H4HBKISO.js";
@@ -1541,10 +1542,29 @@ async function resumeSlackTurnInContext(args) {
1541
1542
  providerDisplayName: outcome.providerDisplayName
1542
1543
  });
1543
1544
  };
1544
- } else if (outcome.status === "suspended" && onSuspend) {
1545
- deferredPauseHandler = async () => {
1546
- await onSuspend(outcome.resumeVersion);
1547
- };
1545
+ } else if (outcome.status === "suspended") {
1546
+ if (runArgs.ownsConversationLease && (outcome.reason === "timeout" || activeReplyContext.durability?.shouldYield?.())) {
1547
+ throw new CooperativeTurnYieldError();
1548
+ }
1549
+ if (onSuspend) {
1550
+ deferredPauseHandler = async () => {
1551
+ await onSuspend(outcome.resumeVersion);
1552
+ };
1553
+ } else {
1554
+ deferredFailureHandler = async () => {
1555
+ await handleResumeFailure({
1556
+ body: "Failed to resume Slack turn",
1557
+ error: new Error(
1558
+ `Resumed run ended suspended without a pause handler`
1559
+ ),
1560
+ eventName: "slack.resume.turn.failed",
1561
+ failureCode: "agent_run_failed",
1562
+ turnLifecycle,
1563
+ lockKey,
1564
+ resumeArgs: runArgs
1565
+ });
1566
+ };
1567
+ }
1548
1568
  } else {
1549
1569
  deferredFailureHandler = async () => {
1550
1570
  await handleResumeFailure({
@@ -1645,6 +1665,13 @@ async function resumeSlackTurnInContext(args) {
1645
1665
  }
1646
1666
  } catch (error) {
1647
1667
  await status.clear();
1668
+ if (isCooperativeTurnYieldError(error)) {
1669
+ if (lock) {
1670
+ await stateAdapter.releaseLock(lock);
1671
+ }
1672
+ await processingReaction?.stop();
1673
+ throw error;
1674
+ }
1648
1675
  if (runResultHandled) {
1649
1676
  postDeliveryCommitError = error;
1650
1677
  try {
@@ -1786,7 +1813,7 @@ async function wakePausedTurn(request, options = {}) {
1786
1813
 
1787
1814
  // src/handlers/oauth-html.ts
1788
1815
  function htmlCallbackResponse(title, message, status, options = {}) {
1789
- 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}.`;
1790
1817
  const html = `<!DOCTYPE html>
1791
1818
  <html>
1792
1819
  <head><title>${title}</title></head>
@@ -1811,38 +1838,40 @@ function htmlCallbackResponse(title, message, status, options = {}) {
1811
1838
  }
1812
1839
 
1813
1840
  // src/handlers/mcp-oauth-callback.ts
1814
- var CALLBACK_PAGES = {
1815
- missing_state: {
1816
- title: "Authorization failed",
1817
- message: "Missing state parameter.",
1818
- status: 400
1819
- },
1820
- provider_error: {
1821
- title: "Authorization failed",
1822
- message: "The provider returned an authorization error.",
1823
- status: 400
1824
- },
1825
- missing_code: {
1826
- title: "Authorization failed",
1827
- message: "Missing code parameter.",
1828
- status: 400
1829
- },
1830
- expired: {
1831
- title: "Authorization expired",
1832
- message: "This authorization link is no longer active. Return to Junior and retry the original request.",
1833
- status: 400
1834
- },
1835
- success: {
1836
- title: "Authorization complete",
1837
- message: "Your MCP access is connected. Junior will continue the paused request in Slack.",
1838
- status: 200
1839
- },
1840
- failure: {
1841
- title: "Authorization failed",
1842
- message: "Junior could not finish the authorization callback. Return to Junior and retry the original request.",
1843
- status: 500
1844
- }
1845
- };
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
+ }
1846
1875
  var McpOAuthAttemptExpiredError = class extends Error {
1847
1876
  constructor() {
1848
1877
  super("MCP OAuth authorization attempt is no longer current");
@@ -1853,11 +1882,13 @@ function mcpAuthorizationId(args) {
1853
1882
  return `${args.sessionId}:mcp:${args.provider}`;
1854
1883
  }
1855
1884
  function htmlResponse(kind, options) {
1885
+ const botName = botConfig.userName;
1886
+ const pages = callbackPages(botName);
1856
1887
  const page = kind === "success" && options?.local ? {
1857
- ...CALLBACK_PAGES.success,
1858
- message: "Your MCP access is connected. Junior will continue the paused request in the local client."
1859
- } : CALLBACK_PAGES[kind];
1860
- 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;
1861
1892
  return htmlCallbackResponse(page.title, page.message, page.status, {
1862
1893
  footerMessage
1863
1894
  });
@@ -2167,7 +2198,7 @@ async function isCurrentMcpAuthorizationAttempt(authSession, provider) {
2167
2198
  return pendingAuth?.authSessionId === authSession.authSessionId && pendingAuth.sessionId === authSession.sessionId;
2168
2199
  }
2169
2200
  function mcpConversationId(authSession) {
2170
- if (authSession.destination?.platform === "local") {
2201
+ if (authSession.destination?.platform === "local" || authSession.source?.platform === "web") {
2171
2202
  return authSession.conversationId;
2172
2203
  }
2173
2204
  if (authSession.channelId && authSession.threadTs) {
@@ -2263,7 +2294,40 @@ async function GET(request, provider, waitUntil, options) {
2263
2294
  "app.credential.provider": provider
2264
2295
  });
2265
2296
  }
2266
- 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") {
2267
2331
  waitUntil(
2268
2332
  () => resumeAuthorizedMcpTurn({
2269
2333
  authSession,
@@ -2273,7 +2337,9 @@ async function GET(request, provider, waitUntil, options) {
2273
2337
  );
2274
2338
  }
2275
2339
  return htmlResponse("success", {
2276
- 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"
2277
2343
  });
2278
2344
  } catch (callbackError) {
2279
2345
  if (callbackError instanceof McpOAuthAttemptExpiredError) {
@@ -2998,7 +3064,7 @@ async function GET2(request, provider, waitUntil, options) {
2998
3064
  { "app.credential.provider": provider }
2999
3065
  );
3000
3066
  }
3001
- if (stored.destination?.platform !== "local") {
3067
+ if (stored.destination?.platform !== "local" && stored.source?.platform !== "web") {
3002
3068
  waitUntil(async () => {
3003
3069
  try {
3004
3070
  await publishAppHomeView(
@@ -3010,10 +3076,46 @@ async function GET2(request, provider, waitUntil, options) {
3010
3076
  }
3011
3077
  });
3012
3078
  }
3079
+ const resumesWebTurn = Boolean(
3080
+ stored.source?.platform === "web" && stored.destination && stored.resumeConversationId && stored.resumeSessionId
3081
+ );
3013
3082
  const resumesAgentTurn = Boolean(
3014
3083
  stored.destination?.platform !== "local" && stored.resumeConversationId && stored.resumeSessionId
3015
3084
  );
3016
- 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) {
3017
3119
  waitUntil(
3018
3120
  () => withLogContext(
3019
3121
  { conversationId: stored.resumeConversationId },
@@ -3045,8 +3147,9 @@ async function GET2(request, provider, waitUntil, options) {
3045
3147
  })
3046
3148
  );
3047
3149
  }
3048
- 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.`;
3049
- 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.";
3050
3153
  return htmlCallbackResponse(
3051
3154
  escapeXml(`${providerLabel} account connected`),
3052
3155
  escapeXml(statusMessage),
@@ -0,0 +1,89 @@
1
+ import {
2
+ getStateAdapter
3
+ } from "./chunk-X6JP6AMX.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
+ };
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  appendAndEnqueueInboundMessage
3
- } from "./chunk-JVOLC6JZ.js";
3
+ } from "./chunk-AYPU5T5L.js";
4
4
  import {
5
5
  ConversationTurnLifecycleService,
6
6
  getPersistedSandboxState,
7
7
  getPersistedThreadState,
8
8
  persistThreadStateById
9
- } from "./chunk-JBYWR6FW.js";
9
+ } from "./chunk-67VR4BJK.js";
10
10
  import {
11
11
  AgentInvocationBusyError,
12
12
  AgentInvocationLimitError,
@@ -15,7 +15,7 @@ import {
15
15
  agentBindingSchema,
16
16
  agentInvocationSchema,
17
17
  createAgentInvocationSchema
18
- } from "./chunk-IZE2EGCX.js";
18
+ } from "./chunk-UFKSILED.js";
19
19
  import {
20
20
  TurnInputCommitLostError,
21
21
  failTurnRecord,
@@ -26,16 +26,16 @@ import {
26
26
  isTurnInputCommitLostError,
27
27
  openConversationProjection,
28
28
  saveTurnCheckpoint
29
- } from "./chunk-2AWDPNP7.js";
29
+ } from "./chunk-3PCKG4BT.js";
30
30
  import {
31
31
  getConversationEventStore,
32
32
  getConversationStore,
33
33
  getSqlExecutor
34
- } from "./chunk-GZ25ZSTX.js";
34
+ } from "./chunk-XTLF7C4I.js";
35
35
  import {
36
36
  juniorAgentBindings,
37
37
  juniorAgentInvocations
38
- } from "./chunk-KFHJQYKQ.js";
38
+ } from "./chunk-X4RM4TBW.js";
39
39
 
40
40
  // src/chat/agent-invocations/work.ts
41
41
  import { z } from "zod";
@@ -4,7 +4,7 @@ import {
4
4
  import {
5
5
  formatProviderLabel,
6
6
  startOAuthFlow
7
- } from "./chunk-SZ74ECCC.js";
7
+ } from "./chunk-QKPIW2CY.js";
8
8
  import {
9
9
  parseSandboxEgressAuthRequiredSignal
10
10
  } from "./chunk-HUO3UTAQ.js";
@@ -12,16 +12,16 @@ import {
12
12
  abandonReplacedPendingAuth,
13
13
  canReusePendingAuthLink,
14
14
  recordAuthorizationRequested
15
- } from "./chunk-2AWDPNP7.js";
15
+ } from "./chunk-3PCKG4BT.js";
16
16
  import {
17
17
  AGENT_INVOCATION_MAILBOX_STATUSES
18
- } from "./chunk-KFHJQYKQ.js";
18
+ } from "./chunk-X4RM4TBW.js";
19
19
  import {
20
20
  TURN_REASONING_LEVELS
21
- } from "./chunk-FGP5W3NS.js";
21
+ } from "./chunk-OEECXAGT.js";
22
22
  import {
23
23
  pluginCatalogRuntime
24
- } from "./chunk-2DIRU2C2.js";
24
+ } from "./chunk-WZN4RQ64.js";
25
25
  import {
26
26
  credentialContextSchema
27
27
  } from "./chunk-RUIXF3YQ.js";
@@ -118,7 +118,13 @@ var conversationPendingMessageSchema = z2.object({
118
118
  });
119
119
  }
120
120
  });
121
+ var conversationPendingAuthorizationSchema = z2.object({
122
+ authorizationUrl: z2.string().url(),
123
+ completionText: z2.string().min(1),
124
+ label: z2.string().min(1)
125
+ }).strict();
121
126
  var conversationPendingMessagesReportSchema = z2.object({
127
+ authorization: conversationPendingAuthorizationSchema.optional(),
122
128
  conversationId: z2.string().min(1),
123
129
  generatedAt: z2.string().datetime(),
124
130
  messages: z2.array(conversationPendingMessageSchema)
@@ -177,6 +183,7 @@ var conversationReportMessageEventDataSchema = z2.object({
177
183
  source: z2.literal("web").optional(),
178
184
  actorIdentity: actorIdentitySchema.optional(),
179
185
  eventType: z2.string().min(1).optional(),
186
+ explicitMention: z2.boolean().optional(),
180
187
  text: z2.string().optional(),
181
188
  redacted: z2.literal(true).optional()
182
189
  }).strict().superRefine((data, context) => {
@@ -278,7 +285,13 @@ var conversationReportTurnLifecycleEventDataSchema = z2.discriminatedUnion(
278
285
  z2.object({
279
286
  type: z2.literal("turn_lifecycle"),
280
287
  turnId: z2.string().min(1),
281
- state: z2.enum(["started", "succeeded", "no_reply"])
288
+ state: z2.enum(["succeeded", "no_reply"])
289
+ }).strict(),
290
+ z2.object({
291
+ type: z2.literal("turn_lifecycle"),
292
+ turnId: z2.string().min(1),
293
+ state: z2.literal("started"),
294
+ inputMessageIds: z2.array(z2.string().min(1)).min(1).optional()
282
295
  }).strict(),
283
296
  z2.object({
284
297
  type: z2.literal("turn_lifecycle"),
@@ -777,6 +790,7 @@ export {
777
790
  acceptedConversationMessageSchema,
778
791
  conversationPendingMessageDeliverySchema,
779
792
  conversationPendingMessageSchema,
793
+ conversationPendingAuthorizationSchema,
780
794
  conversationPendingMessagesReportSchema,
781
795
  conversationAuxiliaryCostsSchema,
782
796
  conversationSummaryReportSchema,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  pluginCatalogRuntime
3
- } from "./chunk-2DIRU2C2.js";
3
+ } from "./chunk-WZN4RQ64.js";
4
4
 
5
5
  // src/chat/plugins/validation.ts
6
6
  import { isDeepStrictEqual } from "util";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createPluginCatalogRuntime
3
- } from "./chunk-TZRYLW3R.js";
3
+ } from "./chunk-CLX3T7Q3.js";
4
4
 
5
5
  // src/chat/plugins/catalog-runtime.ts
6
6
  var pluginCatalogRuntime = createPluginCatalogRuntime();
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  DEFAULT_SQL_STATEMENT_TIMEOUT_MS
3
- } from "./chunk-FGP5W3NS.js";
3
+ } from "./chunk-OEECXAGT.js";
4
4
  import {
5
5
  juniorDestinations,
6
6
  timestamptz
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getChatConfig
3
- } from "./chunk-FGP5W3NS.js";
3
+ } from "./chunk-OEECXAGT.js";
4
4
 
5
5
  // src/chat/state/adapter.ts
6
6
  import { createMemoryState } from "@chat-adapter/state-memory";