@sentry/junior 0.113.0 → 0.115.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 (98) hide show
  1. package/dist/{agent-hooks-BKEMWR3Z.js → agent-hooks-4EUUXP2F.js} +12 -11
  2. package/dist/api/conversations/detail.d.ts +26 -0
  3. package/dist/api/conversations/event-list.d.ts +26 -0
  4. package/dist/api/conversations/events.d.ts +1 -1
  5. package/dist/api/health.d.ts +7 -0
  6. package/dist/api/plugin-reports.d.ts +62 -0
  7. package/dist/api/plugins.d.ts +9 -0
  8. package/dist/api/runtime.d.ts +24 -0
  9. package/dist/api/schema/conversation.d.ts +104 -0
  10. package/dist/api/schema.d.ts +2 -2
  11. package/dist/api/schema.js +6 -6
  12. package/dist/api/skills.d.ts +6 -0
  13. package/dist/api.js +140 -100
  14. package/dist/app.d.ts +2 -0
  15. package/dist/app.js +1117 -5010
  16. package/dist/catalog-runtime-Y32UEQLB.js +18 -0
  17. package/dist/chat/agent/request.d.ts +6 -0
  18. package/dist/chat/agent/sandbox.d.ts +2 -0
  19. package/dist/chat/agent/tools.d.ts +2 -0
  20. package/dist/chat/config.d.ts +3 -1
  21. package/dist/chat/conversations/history.d.ts +92 -0
  22. package/dist/chat/conversations/projection.d.ts +20 -1
  23. package/dist/chat/local/credential-sync.d.ts +5 -0
  24. package/dist/chat/local/oauth-relay.d.ts +4 -0
  25. package/dist/chat/mcp/oauth.d.ts +1 -0
  26. package/dist/chat/oauth-authorization.d.ts +17 -0
  27. package/dist/chat/oauth-flow.d.ts +9 -0
  28. package/dist/chat/sandbox/egress/schemas.d.ts +46 -0
  29. package/dist/chat/sandbox/egress/signals.d.ts +9 -0
  30. package/dist/chat/sandbox/sandbox.d.ts +2 -0
  31. package/dist/chat/sentry-payload-filter.d.ts +4 -4
  32. package/dist/chat/services/context-budget.d.ts +7 -2
  33. package/dist/chat/services/context-compaction.d.ts +28 -1
  34. package/dist/chat/services/conversation-memory.d.ts +1 -0
  35. package/dist/chat/services/mcp-auth-orchestration.d.ts +5 -3
  36. package/dist/chat/services/plugin-auth-orchestration.d.ts +2 -0
  37. package/dist/chat/services/provider-error.d.ts +1 -0
  38. package/dist/chat/services/turn-router.d.ts +1 -0
  39. package/dist/chat/slack/message-control.d.ts +2 -0
  40. package/dist/chat/slack/oauth-authorization-message.d.ts +3 -0
  41. package/dist/chat/task-execution/slack-work.d.ts +2 -0
  42. package/dist/chat/tool-support/zod-tool.d.ts +1 -1
  43. package/dist/chat/tools/definition.d.ts +5 -0
  44. package/dist/chat/tools/sandbox/edit-file.d.ts +1 -1
  45. package/dist/chat/tools/sandbox/text-edits.d.ts +1 -0
  46. package/dist/{chunk-4WZ7YKDF.js → chunk-2QG4MZQ7.js} +2 -2
  47. package/dist/{chunk-H5ON7XTE.js → chunk-43RYMWJ2.js} +954 -2514
  48. package/dist/chunk-4CODA7P5.js +43 -0
  49. package/dist/{chunk-HMRVILWZ.js → chunk-67CVNDJ7.js} +1 -1
  50. package/dist/{chunk-LR2SKL5Y.js → chunk-6FKLPVF3.js} +1 -1
  51. package/dist/{chunk-2ZTTXTSZ.js → chunk-6OPTF4BQ.js} +10 -4
  52. package/dist/{chunk-3CTIAKSS.js → chunk-6V762AB4.js} +1 -1
  53. package/dist/{chunk-WBB22ANL.js → chunk-AGLQYELI.js} +77 -8
  54. package/dist/{chunk-DXRPHBOU.js → chunk-CEYOL62C.js} +77 -36
  55. package/dist/{chunk-QTS66GMR.js → chunk-CWEZEPD4.js} +3 -3
  56. package/dist/chunk-DIB4GX3G.js +8 -0
  57. package/dist/{chunk-OXE5ZUTS.js → chunk-EW5MLKT5.js} +10 -75
  58. package/dist/{chunk-42WRQLJ6.js → chunk-F3B2YJ76.js} +0 -14
  59. package/dist/chunk-FA6POGLH.js +70 -0
  60. package/dist/{chunk-ZRSUCJGA.js → chunk-FHC4JUSF.js} +1 -1
  61. package/dist/{chunk-6Y5L4BOM.js → chunk-FXOYURO4.js} +5 -3
  62. package/dist/{chunk-UKGNSJQQ.js → chunk-G36V2YGB.js} +108 -82
  63. package/dist/{chunk-K5BXPM74.js → chunk-G5SX4UPR.js} +3 -43
  64. package/dist/chunk-HDSDCEPK.js +80 -0
  65. package/dist/{chunk-LLKDNPYV.js → chunk-HWCQRGLL.js} +37 -3
  66. package/dist/{chunk-C4MZ3GP5.js → chunk-HZF5P5UN.js} +1 -1
  67. package/dist/chunk-LYA2AB5G.js +1914 -0
  68. package/dist/{chunk-36UJA3OD.js → chunk-NVUQSFWX.js} +2 -2
  69. package/dist/chunk-OB42YVAE.js +16 -0
  70. package/dist/{chunk-4VKFQPCW.js → chunk-PVZHG2XZ.js} +4 -4
  71. package/dist/{chunk-YJ44UT7D.js → chunk-RAVKCKXA.js} +7 -7
  72. package/dist/{chunk-RCBUZGIT.js → chunk-SYJT7AKB.js} +23 -20
  73. package/dist/{chunk-NP7TYFYR.js → chunk-TVE25LPW.js} +1 -1
  74. package/dist/chunk-W3U3YQYI.js +71 -0
  75. package/dist/chunk-YCLO7D7M.js +4267 -0
  76. package/dist/cli/chat.js +72 -40
  77. package/dist/cli/check.js +10 -8
  78. package/dist/cli/init.js +1 -0
  79. package/dist/cli/plugins.js +16 -14
  80. package/dist/cli/snapshot-warmup.js +13 -11
  81. package/dist/cli/upgrade.js +10 -8
  82. package/dist/{db-2ASK6MV6.js → db-KBSJHAZU.js} +8 -7
  83. package/dist/handlers/sandbox-egress-signals.d.ts +4 -0
  84. package/dist/instrumentation.js +72 -4
  85. package/dist/nitro.js +2 -2
  86. package/dist/oauth-callback-server-EYRMJTCS.js +231 -0
  87. package/dist/oauth-relay-3ZU72UGL.js +9 -0
  88. package/dist/reporting-schema.d.ts +12 -4
  89. package/dist/reporting.d.ts +5 -5
  90. package/dist/{runner-L363K62Z.js → runner-RQGZ5Z2S.js} +139 -72
  91. package/dist/sandbox-egress-signals-CDFAP67O.js +75 -0
  92. package/dist/{skills-VCPG3NOO.js → skills-JJQIE3BT.js} +10 -8
  93. package/dist/validation-MZ47PZP5.js +21 -0
  94. package/dist/version.js +1 -1
  95. package/package.json +5 -5
  96. package/dist/catalog-runtime-6XYOUVRZ.js +0 -16
  97. package/dist/chat/oauth-authorization-message.d.ts +0 -6
  98. package/dist/validation-GY7AJBLC.js +0 -19
@@ -0,0 +1,43 @@
1
+ import {
2
+ getClient
3
+ } from "./chunk-6GWA276C.js";
4
+
5
+ // src/chat/sentry-links.ts
6
+ function getSentryOrgSlug() {
7
+ const slug = process.env.SENTRY_ORG_SLUG?.trim();
8
+ return slug || void 0;
9
+ }
10
+ function isSentrySaasDsnHost(host) {
11
+ return host === "sentry.io" || host.endsWith(".sentry.io");
12
+ }
13
+ function buildSentryWebBaseUrl(dsn) {
14
+ if (isSentrySaasDsnHost(dsn.host)) {
15
+ return "https://sentry.io";
16
+ }
17
+ const port = dsn.port ? `:${dsn.port}` : "";
18
+ const path = dsn.path ? `/${dsn.path}` : "";
19
+ return `${dsn.protocol}://${dsn.host}${port}${path}`;
20
+ }
21
+ function buildSentryConversationUrl(conversationId) {
22
+ const client = getClient();
23
+ const dsn = client?.getDsn();
24
+ if (!dsn?.host || !dsn.projectId) {
25
+ return void 0;
26
+ }
27
+ const orgSlug = getSentryOrgSlug();
28
+ if (!orgSlug) {
29
+ return void 0;
30
+ }
31
+ const encodedId = encodeURIComponent(conversationId);
32
+ const params = new URLSearchParams();
33
+ params.set("project", dsn.projectId);
34
+ const path = `explore/conversations/${encodedId}/?${params.toString()}`;
35
+ if (isSentrySaasDsnHost(dsn.host)) {
36
+ return `https://${orgSlug}.sentry.io/${path}`;
37
+ }
38
+ return `${buildSentryWebBaseUrl(dsn)}/organizations/${orgSlug}/${path}`;
39
+ }
40
+
41
+ export {
42
+ buildSentryConversationUrl
43
+ };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getChatConfig
3
- } from "./chunk-RCBUZGIT.js";
3
+ } from "./chunk-SYJT7AKB.js";
4
4
 
5
5
  // src/chat/state/adapter.ts
6
6
  import { createMemoryState } from "@chat-adapter/state-memory";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createPluginCatalogRuntime
3
- } from "./chunk-OXE5ZUTS.js";
3
+ } from "./chunk-EW5MLKT5.js";
4
4
 
5
5
  // src/chat/plugins/catalog-runtime.ts
6
6
  var pluginCatalogRuntime = createPluginCatalogRuntime();
@@ -5,8 +5,14 @@ var healthReportSchema = z.object({
5
5
  service: z.string(),
6
6
  timestamp: z.string()
7
7
  }).strict();
8
- var pluginReportSchema = z.object({ name: z.string() }).strict();
9
- var pluginReportsSchema = z.array(pluginReportSchema);
8
+ var pluginSchema = z.object({
9
+ capabilities: z.array(z.string()),
10
+ configKeys: z.array(z.string()),
11
+ description: z.string(),
12
+ displayName: z.string(),
13
+ name: z.string()
14
+ }).strict();
15
+ var pluginsSchema = z.array(pluginSchema);
10
16
  var skillReportSchema = z.object({
11
17
  name: z.string(),
12
18
  pluginProvider: z.string().optional()
@@ -97,8 +103,8 @@ var pluginOperationalReportFeedSchema = z.object({
97
103
 
98
104
  export {
99
105
  healthReportSchema,
100
- pluginReportSchema,
101
- pluginReportsSchema,
106
+ pluginSchema,
107
+ pluginsSchema,
102
108
  skillReportSchema,
103
109
  skillReportsSchema,
104
110
  pluginPackageContentItemReportSchema,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  pluginCatalogRuntime
3
- } from "./chunk-LR2SKL5Y.js";
3
+ } from "./chunk-6FKLPVF3.js";
4
4
 
5
5
  // src/chat/plugins/validation.ts
6
6
  import { isDeepStrictEqual } from "util";
@@ -4,6 +4,7 @@ import {
4
4
  sendVercelPluginTask
5
5
  } from "./chunk-KNFROR7R.js";
6
6
  import {
7
+ buildDeterministicTurnId,
7
8
  clearPendingAuth,
8
9
  coerceThreadConversationState,
9
10
  getAgentTurnSessionRecord,
@@ -15,36 +16,38 @@ import {
15
16
  isToolResultError,
16
17
  isToolResultMessage,
17
18
  markConversationMessage,
19
+ markTurnClosed,
18
20
  markTurnCompleted,
19
21
  mergeArtifactsState,
20
22
  normalizeToolNameFromResult,
23
+ persistThreadStateById,
21
24
  stripRuntimeTurnContext,
22
25
  updateConversationStats
23
- } from "./chunk-DXRPHBOU.js";
26
+ } from "./chunk-CEYOL62C.js";
24
27
  import {
25
28
  createPluginEmbedder,
26
29
  createPluginLogger,
27
30
  createPluginModel,
28
31
  createPluginState,
29
32
  getPlugins
30
- } from "./chunk-YJ44UT7D.js";
33
+ } from "./chunk-RAVKCKXA.js";
31
34
  import {
32
35
  getStateAdapter
33
- } from "./chunk-HMRVILWZ.js";
36
+ } from "./chunk-67CVNDJ7.js";
34
37
  import {
35
38
  getDb
36
- } from "./chunk-LLKDNPYV.js";
39
+ } from "./chunk-HWCQRGLL.js";
37
40
  import {
38
41
  ProviderError,
39
42
  getProviderErrorAttributes,
40
43
  getProviderErrorUserMessage
41
- } from "./chunk-RCBUZGIT.js";
44
+ } from "./chunk-SYJT7AKB.js";
42
45
  import {
43
46
  buildTurnFailureResponse
44
- } from "./chunk-36UJA3OD.js";
47
+ } from "./chunk-NVUQSFWX.js";
45
48
  import {
46
49
  parseSlackMessageTs
47
- } from "./chunk-42WRQLJ6.js";
50
+ } from "./chunk-F3B2YJ76.js";
48
51
 
49
52
  // src/chat/services/turn-failure-response.ts
50
53
  function requireTurnFailureEventId(eventId, eventName) {
@@ -523,6 +526,66 @@ function buildDeliveredTurnStatePatch(args) {
523
526
  };
524
527
  }
525
528
 
529
+ // src/chat/runtime/turn-user-message.ts
530
+ function getTurnUserMessage(conversation, sessionId) {
531
+ for (let index = conversation.messages.length - 1; index >= 0; index -= 1) {
532
+ const message = conversation.messages[index];
533
+ if (message?.role !== "user") {
534
+ continue;
535
+ }
536
+ if (buildDeterministicTurnId(message.id) === sessionId) {
537
+ return message;
538
+ }
539
+ }
540
+ return void 0;
541
+ }
542
+ function getTurnUserMessageId(conversation, sessionId) {
543
+ return getTurnUserMessage(conversation, sessionId)?.id;
544
+ }
545
+ function getTurnUserSlackMessageTs(message) {
546
+ return parseSlackMessageTs(message?.meta?.slackTs);
547
+ }
548
+ function getTurnUserReplyAttachmentContext(message) {
549
+ const inboundAttachmentCount = message?.meta?.attachmentCount ?? 0;
550
+ const imageAttachmentCount = message?.meta?.imageAttachmentCount ?? 0;
551
+ const imagesHydrated = message?.meta?.imagesHydrated === true;
552
+ return {
553
+ ...inboundAttachmentCount > 0 ? { inboundAttachmentCount } : {},
554
+ ...!imagesHydrated && imageAttachmentCount > 0 ? { omittedImageAttachmentCount: imageAttachmentCount } : {}
555
+ };
556
+ }
557
+
558
+ // src/chat/runtime/auth-pause-state.ts
559
+ function completeAuthPauseTurn(args) {
560
+ markConversationMessage(
561
+ args.conversation,
562
+ getTurnUserMessageId(args.conversation, args.sessionId),
563
+ {
564
+ replied: true,
565
+ skippedReason: void 0
566
+ }
567
+ );
568
+ markTurnClosed({
569
+ conversation: args.conversation,
570
+ nowMs: Date.now(),
571
+ sessionId: args.sessionId,
572
+ updateConversationStats
573
+ });
574
+ }
575
+ async function persistAuthPauseTurnState(args) {
576
+ const currentState = await getPersistedThreadState(args.threadStateId);
577
+ const conversation = coerceThreadConversationState(currentState);
578
+ await hydrateConversationMessages({
579
+ conversation,
580
+ conversationId: args.threadStateId
581
+ });
582
+ completeAuthPauseTurn({
583
+ conversation,
584
+ sessionId: args.sessionId
585
+ });
586
+ await persistThreadStateById(args.threadStateId, { conversation });
587
+ }
588
+
526
589
  export {
527
590
  requireTurnFailureEventId,
528
591
  getAgentTurnDiagnosticsAttributes,
@@ -530,5 +593,11 @@ export {
530
593
  ConversationTurnLifecycleService,
531
594
  scheduleSessionCompletedPluginTasks,
532
595
  processPluginTask,
533
- buildDeliveredTurnStatePatch
596
+ buildDeliveredTurnStatePatch,
597
+ getTurnUserMessage,
598
+ getTurnUserMessageId,
599
+ getTurnUserSlackMessageTs,
600
+ getTurnUserReplyAttachmentContext,
601
+ completeAuthPauseTurn,
602
+ persistAuthPauseTurnState
534
603
  };
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-MU6HHZEN.js";
5
5
  import {
6
6
  getStateAdapter
7
- } from "./chunk-HMRVILWZ.js";
7
+ } from "./chunk-67CVNDJ7.js";
8
8
  import {
9
9
  contextProvenance,
10
10
  createSqlConversationEventStore,
@@ -15,7 +15,7 @@ import {
15
15
  instructionProvenanceFor,
16
16
  sanitizePostgresJson,
17
17
  withConversationEventLock
18
- } from "./chunk-LLKDNPYV.js";
18
+ } from "./chunk-HWCQRGLL.js";
19
19
  import {
20
20
  sleep
21
21
  } from "./chunk-4ZNGQH7C.js";
@@ -23,24 +23,25 @@ import {
23
23
  botConfig,
24
24
  escapeXml,
25
25
  resolveGatewayModel,
26
- standardModelId,
27
26
  unwrapCurrentInstruction
28
- } from "./chunk-RCBUZGIT.js";
27
+ } from "./chunk-SYJT7AKB.js";
29
28
  import {
30
29
  toStoredSlackActor
31
- } from "./chunk-C4MZ3GP5.js";
30
+ } from "./chunk-HZF5P5UN.js";
32
31
  import {
33
32
  getActiveTraceId,
34
33
  logException,
35
34
  logWarn,
36
35
  setSpanAttributes
37
- } from "./chunk-36UJA3OD.js";
36
+ } from "./chunk-NVUQSFWX.js";
38
37
  import {
39
38
  isRecord,
40
- parseSlackMessageTs,
41
39
  toOptionalNumber,
42
40
  toOptionalString
43
- } from "./chunk-42WRQLJ6.js";
41
+ } from "./chunk-OB42YVAE.js";
42
+ import {
43
+ parseSlackMessageTs
44
+ } from "./chunk-F3B2YJ76.js";
44
45
 
45
46
  // src/chat/turn-context-tag.ts
46
47
  var TURN_CONTEXT_TAG = "runtime-turn-context";
@@ -451,6 +452,36 @@ async function recordAuthorizationCompleted(args) {
451
452
  }
452
453
  ]);
453
454
  }
455
+ async function loadTurnRoute(args) {
456
+ const event = await getConversationEventStore().loadByIdempotencyKey(
457
+ args.conversationId,
458
+ `turn:${args.turnId}:routed`
459
+ );
460
+ if (!event) {
461
+ return void 0;
462
+ }
463
+ if (event.data.type !== "turn_routed" || event.data.turnId !== args.turnId) {
464
+ throw new Error(`Turn route key for "${args.turnId}" has invalid data`);
465
+ }
466
+ return event.data;
467
+ }
468
+ async function recordTurnRoute(args) {
469
+ await getConversationEventStore().append(args.conversationId, [
470
+ {
471
+ idempotencyKey: `turn:${args.turnId}:routed`,
472
+ createdAtMs: Date.now(),
473
+ data: {
474
+ type: "turn_routed",
475
+ turnId: args.turnId,
476
+ modelProfile: args.modelProfile,
477
+ modelId: args.modelId,
478
+ reasoningLevel: args.reasoningLevel,
479
+ ...args.confidence !== void 0 ? { confidence: args.confidence } : {},
480
+ source: args.source
481
+ }
482
+ }
483
+ ]);
484
+ }
454
485
  async function recordToolExecutionStarted(args) {
455
486
  await getConversationEventStore().append(args.conversationId, [
456
487
  {
@@ -1588,11 +1619,10 @@ function buildConversationStatePatch(conversation) {
1588
1619
  }
1589
1620
 
1590
1621
  // src/chat/services/context-budget.ts
1591
- var COMPACTION_TRIGGER_INPUT_RATIO = 0.75;
1592
- var COMPACTION_OUTPUT_RESERVE_RATIO = 0.25;
1622
+ var COMPACTION_TRIGGER_RATIO = 0.9;
1623
+ var CONTEXT_INPUT_LIMIT_RATIO = 0.95;
1593
1624
  var COMPACTION_TARGET_RATIO = 0.8;
1594
1625
  var FALLBACK_CONTEXT_WINDOW_TOKENS = 4e5;
1595
- var FALLBACK_MAX_OUTPUT_TOKENS = 128e3;
1596
1626
  function positiveInteger(value, fallback) {
1597
1627
  return Number.isFinite(value) && value > 0 ? Math.floor(value) : fallback;
1598
1628
  }
@@ -1604,36 +1634,43 @@ function calculateContextCompactionTriggerTokens(model) {
1604
1634
  model.contextWindow,
1605
1635
  FALLBACK_CONTEXT_WINDOW_TOKENS
1606
1636
  );
1607
- const maxTokens = positiveInteger(
1608
- model.maxTokens,
1609
- FALLBACK_MAX_OUTPUT_TOKENS
1610
- );
1611
- const outputReserve = Math.min(
1612
- maxTokens,
1613
- Math.floor(contextWindow * COMPACTION_OUTPUT_RESERVE_RATIO)
1614
- );
1615
- const usableInputTokens = Math.max(1, contextWindow - outputReserve);
1616
- return Math.max(
1617
- 1,
1618
- Math.floor(usableInputTokens * COMPACTION_TRIGGER_INPUT_RATIO)
1637
+ return Math.max(1, Math.floor(contextWindow * COMPACTION_TRIGGER_RATIO));
1638
+ }
1639
+ function calculateContextInputLimitTokens(model) {
1640
+ const contextWindow = positiveInteger(
1641
+ model.contextWindow,
1642
+ FALLBACK_CONTEXT_WINDOW_TOKENS
1619
1643
  );
1644
+ return Math.max(1, Math.floor(contextWindow * CONTEXT_INPUT_LIMIT_RATIO));
1620
1645
  }
1621
1646
  function calculateContextCompactionTargetTokens(triggerTokens) {
1622
1647
  return Math.max(1, Math.floor(triggerTokens * COMPACTION_TARGET_RATIO));
1623
1648
  }
1624
- function getAgentContextCompactionTriggerTokens() {
1625
- const model = resolveGatewayModel(standardModelId(botConfig));
1626
- return calculateContextCompactionTriggerTokens({
1627
- contextWindow: botConfig.modelContextWindowTokens ?? model.contextWindow,
1628
- maxTokens: model.maxTokens
1629
- });
1649
+ function getModelContextBudget(modelId) {
1650
+ const model = resolveGatewayModel(modelId);
1651
+ const advertisedContextWindow = positiveInteger(
1652
+ model.contextWindow,
1653
+ FALLBACK_CONTEXT_WINDOW_TOKENS
1654
+ );
1655
+ return {
1656
+ contextWindow: Math.min(
1657
+ botConfig.contextWindowTokens,
1658
+ advertisedContextWindow
1659
+ )
1660
+ };
1661
+ }
1662
+ function getAgentContextCompactionTriggerTokens(modelId) {
1663
+ return calculateContextCompactionTriggerTokens(
1664
+ getModelContextBudget(modelId)
1665
+ );
1666
+ }
1667
+ function getAgentContextInputLimitTokens(modelId) {
1668
+ return calculateContextInputLimitTokens(getModelContextBudget(modelId));
1630
1669
  }
1631
1670
  function getConversationContextCompactionTriggerTokens() {
1632
- const model = resolveGatewayModel(botConfig.fastModelId);
1633
- return calculateContextCompactionTriggerTokens({
1634
- contextWindow: model.contextWindow,
1635
- maxTokens: model.maxTokens
1636
- });
1671
+ return calculateContextCompactionTriggerTokens(
1672
+ getModelContextBudget(botConfig.fastModelId)
1673
+ );
1637
1674
  }
1638
1675
 
1639
1676
  // src/chat/services/conversation-memory.ts
@@ -1646,7 +1683,7 @@ function generateConversationId(prefix) {
1646
1683
  return `${prefix}_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;
1647
1684
  }
1648
1685
  function normalizeConversationText(text) {
1649
- return text.trim().replace(/\s+/g, " ").slice(0, CONTEXT_MAX_MESSAGE_CHARS);
1686
+ return text.replace(/\r\n?/g, "\n").trim();
1650
1687
  }
1651
1688
  function buildImageContextSuffix(message, conversation) {
1652
1689
  const byFileId = conversation?.vision.byFileId;
@@ -1662,6 +1699,7 @@ function buildImageContextSuffix(message, conversation) {
1662
1699
  }
1663
1700
  function renderConversationMessageLine(message, conversation) {
1664
1701
  const displayName = conversationAuthorDisplayName(message);
1702
+ const text = message.text.replace(/\s+/g, " ").slice(0, CONTEXT_MAX_MESSAGE_CHARS);
1665
1703
  const markers = [];
1666
1704
  if (message.meta?.replied === false) {
1667
1705
  markers.push(
@@ -1673,7 +1711,7 @@ function renderConversationMessageLine(message, conversation) {
1673
1711
  }
1674
1712
  const markerSuffix = markers.length > 0 ? ` (${markers.join("; ")})` : "";
1675
1713
  const imageContext = buildImageContextSuffix(message, conversation);
1676
- return `[${message.role}] ${displayName}: ${message.text}${imageContext}${markerSuffix}`;
1714
+ return `[${message.role}] ${displayName}: ${text}${imageContext}${markerSuffix}`;
1677
1715
  }
1678
1716
  function conversationAuthorDisplayName(message) {
1679
1717
  const author = message.author;
@@ -2650,6 +2688,8 @@ export {
2650
2688
  recordMcpProviderConnected,
2651
2689
  recordAuthorizationRequested,
2652
2690
  recordAuthorizationCompleted,
2691
+ loadTurnRoute,
2692
+ recordTurnRoute,
2653
2693
  recordToolExecutionStarted,
2654
2694
  buildDeterministicTurnId,
2655
2695
  buildDeterministicAssistantMessageId,
@@ -2692,6 +2732,7 @@ export {
2692
2732
  persistConversationMessageSummaries,
2693
2733
  estimateTextTokens,
2694
2734
  getAgentContextCompactionTriggerTokens,
2735
+ getAgentContextInputLimitTokens,
2695
2736
  normalizeConversationText,
2696
2737
  updateConversationStats,
2697
2738
  upsertConversationMessage,
@@ -3,16 +3,16 @@ import {
3
3
  } from "./chunk-4ZNGQH7C.js";
4
4
  import {
5
5
  getSlackBotToken
6
- } from "./chunk-RCBUZGIT.js";
6
+ } from "./chunk-SYJT7AKB.js";
7
7
  import {
8
8
  logWarn,
9
9
  setSpanAttributes,
10
10
  setSpanStatus,
11
11
  withSpan
12
- } from "./chunk-36UJA3OD.js";
12
+ } from "./chunk-NVUQSFWX.js";
13
13
  import {
14
14
  parseSlackChannelReferenceId
15
- } from "./chunk-42WRQLJ6.js";
15
+ } from "./chunk-F3B2YJ76.js";
16
16
 
17
17
  // src/chat/slack/client.ts
18
18
  import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
@@ -0,0 +1,8 @@
1
+ // src/chat/oauth-authorization.ts
2
+ function authorizationId(args) {
3
+ return `${args.sessionId}:${args.kind}:${args.provider}`;
4
+ }
5
+
6
+ export {
7
+ authorizationId
8
+ };
@@ -1,11 +1,11 @@
1
1
  import {
2
- parseActorUserId
3
- } from "./chunk-C4MZ3GP5.js";
2
+ credentialUserSubjectId
3
+ } from "./chunk-W3U3YQYI.js";
4
4
  import {
5
5
  logInfo,
6
6
  logWarn,
7
7
  setSpanAttributes
8
- } from "./chunk-36UJA3OD.js";
8
+ } from "./chunk-NVUQSFWX.js";
9
9
  import {
10
10
  discoverInstalledPluginPackageContent,
11
11
  normalizePluginPackageNames
@@ -1083,68 +1083,6 @@ var CredentialUnavailableError = class extends Error {
1083
1083
  }
1084
1084
  };
1085
1085
 
1086
- // src/chat/credentials/context.ts
1087
- import { z as z2 } from "zod";
1088
- var exactActorIdSchema = z2.string().refine((value) => parseActorUserId(value) === value);
1089
- var exactNonBlankStringSchema = z2.string().min(1).refine((value) => value === value.trim());
1090
- var slackDirectCredentialSubjectBindingSchema = z2.object({
1091
- type: z2.literal("slack-direct-conversation"),
1092
- teamId: z2.string().min(1),
1093
- channelId: z2.string().min(1),
1094
- signature: z2.string().min(1)
1095
- }).strict();
1096
- var scheduledTaskCredentialSubjectBindingSchema = z2.object({
1097
- type: z2.literal("scheduled-task"),
1098
- plugin: z2.string().min(1),
1099
- taskId: exactNonBlankStringSchema,
1100
- signature: z2.string().min(1)
1101
- }).strict();
1102
- var credentialSubjectBindingSchema = z2.discriminatedUnion("type", [
1103
- slackDirectCredentialSubjectBindingSchema,
1104
- scheduledTaskCredentialSubjectBindingSchema
1105
- ]);
1106
- var credentialUserActorSchema = z2.object({
1107
- type: z2.literal("user"),
1108
- userId: exactActorIdSchema
1109
- }).strict();
1110
- var credentialSystemActorSchema = z2.object({
1111
- platform: z2.literal("system"),
1112
- name: exactActorIdSchema
1113
- }).strict();
1114
- var credentialSubjectSchema = z2.discriminatedUnion("allowedWhen", [
1115
- z2.object({
1116
- type: z2.literal("user"),
1117
- userId: exactActorIdSchema,
1118
- allowedWhen: z2.literal("private-direct-conversation"),
1119
- binding: slackDirectCredentialSubjectBindingSchema
1120
- }).strict(),
1121
- z2.object({
1122
- type: z2.literal("user"),
1123
- userId: exactActorIdSchema,
1124
- allowedWhen: z2.literal("scheduled-task"),
1125
- taskId: exactNonBlankStringSchema,
1126
- binding: scheduledTaskCredentialSubjectBindingSchema
1127
- }).strict().refine((subject) => subject.binding.taskId === subject.taskId, {
1128
- message: "Scheduled task credential subject requires task binding",
1129
- path: ["binding"]
1130
- })
1131
- ]);
1132
- var credentialContextSchema = z2.union([
1133
- z2.object({
1134
- actor: credentialUserActorSchema
1135
- }).strict(),
1136
- z2.object({
1137
- actor: credentialSystemActorSchema,
1138
- subject: credentialSubjectSchema.optional()
1139
- }).strict()
1140
- ]);
1141
- function credentialUserSubjectId(context) {
1142
- if ("type" in context.actor) {
1143
- return context.actor.userId;
1144
- }
1145
- return "subject" in context ? context.subject?.userId : void 0;
1146
- }
1147
-
1148
1086
  // src/chat/credentials/header-transforms.ts
1149
1087
  function mergeHeaderTransforms(transforms) {
1150
1088
  const byDomain = /* @__PURE__ */ new Map();
@@ -1277,7 +1215,7 @@ function createApiHeadersBroker(manifest) {
1277
1215
  }
1278
1216
 
1279
1217
  // src/chat/plugins/auth/oauth-request.ts
1280
- import { z as z3 } from "zod";
1218
+ import { z as z2 } from "zod";
1281
1219
  var DEFAULT_TOKEN_CONTENT_TYPE = "application/x-www-form-urlencoded";
1282
1220
  function requireNonEmptyTokenField(data, field) {
1283
1221
  const value = data[field];
@@ -1292,12 +1230,12 @@ function requireTokenResponseObject(data) {
1292
1230
  }
1293
1231
  return data;
1294
1232
  }
1295
- var parsedOAuthTokenResponseSchema = z3.object({
1296
- accessToken: z3.string().min(1),
1297
- refreshToken: z3.string().min(1),
1298
- expiresAt: z3.number().positive().optional(),
1299
- refreshTokenExpiresAt: z3.number().positive().optional(),
1300
- scope: z3.string().min(1).optional()
1233
+ var parsedOAuthTokenResponseSchema = z2.object({
1234
+ accessToken: z2.string().min(1),
1235
+ refreshToken: z2.string().min(1),
1236
+ expiresAt: z2.number().positive().optional(),
1237
+ refreshTokenExpiresAt: z2.number().positive().optional(),
1238
+ scope: z2.string().min(1).optional()
1301
1239
  }).strict();
1302
1240
  function contentTypeToBody(contentType, payload) {
1303
1241
  const mediaType = contentType.split(";", 1)[0]?.trim().toLowerCase();
@@ -2070,9 +2008,6 @@ export {
2070
2008
  parsePluginManifest,
2071
2009
  parseInlinePluginManifest,
2072
2010
  CredentialUnavailableError,
2073
- credentialSubjectSchema,
2074
- credentialContextSchema,
2075
- credentialUserSubjectId,
2076
2011
  hasRequiredOAuthScope,
2077
2012
  resolvePluginCommandEnv,
2078
2013
  resolveAuthTokenPlaceholder,
@@ -1,14 +1,3 @@
1
- // src/chat/coerce.ts
2
- function toOptionalString(value) {
3
- return typeof value === "string" && value.trim() ? value : void 0;
4
- }
5
- function toOptionalNumber(value) {
6
- return typeof value === "number" && Number.isFinite(value) ? value : void 0;
7
- }
8
- function isRecord(value) {
9
- return typeof value === "object" && value !== null;
10
- }
11
-
12
1
  // src/chat/slack/timestamp.ts
13
2
  import { z } from "zod";
14
3
  var slackMessageTsSchema = z.string().trim().regex(/^\d+(?:\.\d+)?$/).brand();
@@ -60,9 +49,6 @@ function parseSlackUserId(value) {
60
49
  }
61
50
 
62
51
  export {
63
- toOptionalString,
64
- toOptionalNumber,
65
- isRecord,
66
52
  parseSlackMessageTs,
67
53
  parseSlackChannelId,
68
54
  parseSlackChannelReferenceId,
@@ -0,0 +1,70 @@
1
+ // src/chat/local/oauth-relay.ts
2
+ import { randomBytes } from "crypto";
3
+ import { jwtVerify, SignJWT } from "jose";
4
+ import { z } from "zod";
5
+ var LOCAL_OAUTH_STATE_PREFIX = "jr-local";
6
+ var LOCAL_OAUTH_TOKEN_CONTEXT = "junior.local-oauth-relay.v1";
7
+ var LOCAL_OAUTH_TOKEN_TTL = "10m";
8
+ var localOAuthRelayPayloadSchema = z.object({
9
+ aud: z.literal(LOCAL_OAUTH_TOKEN_CONTEXT),
10
+ exp: z.number().int(),
11
+ iss: z.literal(LOCAL_OAUTH_TOKEN_CONTEXT),
12
+ jti: z.string().min(1),
13
+ port: z.number().int().min(1).max(65535)
14
+ }).strict();
15
+ function relayKey() {
16
+ const secret = process.env.JUNIOR_SECRET?.trim();
17
+ if (!secret) {
18
+ throw new Error("Local OAuth requires JUNIOR_SECRET");
19
+ }
20
+ return new TextEncoder().encode(secret);
21
+ }
22
+ async function createLocalOAuthState(port) {
23
+ if (!Number.isSafeInteger(port) || port < 1 || port > 65535) {
24
+ throw new Error("Local OAuth callback port is invalid");
25
+ }
26
+ const token = await new SignJWT({ port }).setProtectedHeader({ alg: "HS256" }).setIssuer(LOCAL_OAUTH_TOKEN_CONTEXT).setAudience(LOCAL_OAUTH_TOKEN_CONTEXT).setJti(randomBytes(24).toString("base64url")).setExpirationTime(LOCAL_OAUTH_TOKEN_TTL).sign(relayKey());
27
+ return `${LOCAL_OAUTH_STATE_PREFIX}.${token}`;
28
+ }
29
+ async function localOAuthRelayPort(state) {
30
+ const prefix = `${LOCAL_OAUTH_STATE_PREFIX}.`;
31
+ if (!state.startsWith(prefix)) {
32
+ return void 0;
33
+ }
34
+ try {
35
+ const { payload } = await jwtVerify(
36
+ state.slice(prefix.length),
37
+ relayKey(),
38
+ {
39
+ algorithms: ["HS256"],
40
+ issuer: LOCAL_OAUTH_TOKEN_CONTEXT,
41
+ audience: LOCAL_OAUTH_TOKEN_CONTEXT
42
+ }
43
+ );
44
+ const parsed = localOAuthRelayPayloadSchema.safeParse(payload);
45
+ return parsed.success ? parsed.data.port : void 0;
46
+ } catch {
47
+ return void 0;
48
+ }
49
+ }
50
+ async function relayLocalOAuthCallback(request) {
51
+ const url = new URL(request.url);
52
+ if (url.searchParams.get("jr_local_relay") === "complete") {
53
+ return void 0;
54
+ }
55
+ const state = url.searchParams.get("state");
56
+ const port = state ? await localOAuthRelayPort(state) : void 0;
57
+ if (!port) {
58
+ return void 0;
59
+ }
60
+ url.protocol = "http:";
61
+ url.hostname = "127.0.0.1";
62
+ url.port = String(port);
63
+ url.searchParams.set("jr_local_relay", "complete");
64
+ return Response.redirect(url, 302);
65
+ }
66
+
67
+ export {
68
+ createLocalOAuthState,
69
+ relayLocalOAuthCallback
70
+ };