@sentry/junior 0.113.0 → 0.114.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 (51) hide show
  1. package/dist/{agent-hooks-BKEMWR3Z.js → agent-hooks-WNBUY4OB.js} +8 -8
  2. package/dist/api/conversations/detail.d.ts +24 -0
  3. package/dist/api/conversations/event-list.d.ts +24 -0
  4. package/dist/api/conversations/events.d.ts +1 -1
  5. package/dist/api/schema/conversation.d.ts +96 -0
  6. package/dist/api/schema.js +1 -1
  7. package/dist/api.js +29 -13
  8. package/dist/app.d.ts +2 -0
  9. package/dist/app.js +30 -21
  10. package/dist/{catalog-runtime-6XYOUVRZ.js → catalog-runtime-6O4M6JGA.js} +5 -5
  11. package/dist/chat/config.d.ts +1 -1
  12. package/dist/chat/conversations/history.d.ts +86 -0
  13. package/dist/chat/conversations/projection.d.ts +20 -1
  14. package/dist/chat/services/context-budget.d.ts +7 -2
  15. package/dist/chat/services/context-compaction.d.ts +28 -1
  16. package/dist/chat/services/conversation-memory.d.ts +1 -0
  17. package/dist/chat/services/provider-error.d.ts +1 -0
  18. package/dist/chat/services/turn-router.d.ts +1 -0
  19. package/dist/chat/tools/sandbox/edit-file.d.ts +1 -1
  20. package/dist/chat/tools/sandbox/text-edits.d.ts +1 -0
  21. package/dist/{chunk-36UJA3OD.js → chunk-4FUEG3QY.js} +1 -1
  22. package/dist/{chunk-NP7TYFYR.js → chunk-5CZ7RETL.js} +1 -1
  23. package/dist/{chunk-DXRPHBOU.js → chunk-6QWPVTMO.js} +72 -33
  24. package/dist/{chunk-WBB22ANL.js → chunk-ABPSDO6M.js} +6 -6
  25. package/dist/{chunk-LLKDNPYV.js → chunk-FIGAF6KL.js} +34 -2
  26. package/dist/{chunk-OXE5ZUTS.js → chunk-K2W4CK7K.js} +1 -1
  27. package/dist/{chunk-K5BXPM74.js → chunk-O4GT7LYB.js} +1 -1
  28. package/dist/{chunk-LR2SKL5Y.js → chunk-OSKEC4XU.js} +1 -1
  29. package/dist/{chunk-ZRSUCJGA.js → chunk-PM3PX42K.js} +1 -1
  30. package/dist/{chunk-QTS66GMR.js → chunk-RD7EJI7H.js} +2 -2
  31. package/dist/{chunk-UKGNSJQQ.js → chunk-S4QDH23A.js} +25 -1
  32. package/dist/{chunk-4WZ7YKDF.js → chunk-TLGM5X2M.js} +2 -2
  33. package/dist/{chunk-YJ44UT7D.js → chunk-VNNBSKCO.js} +5 -5
  34. package/dist/{chunk-3CTIAKSS.js → chunk-W6RDUAO3.js} +1 -1
  35. package/dist/{chunk-H5ON7XTE.js → chunk-WV4UJBAS.js} +369 -79
  36. package/dist/{chunk-4VKFQPCW.js → chunk-XLFBQJUO.js} +4 -4
  37. package/dist/{chunk-HMRVILWZ.js → chunk-YU6PO42Q.js} +1 -1
  38. package/dist/{chunk-RCBUZGIT.js → chunk-ZGXH3REA.js} +12 -19
  39. package/dist/cli/chat.js +19 -19
  40. package/dist/cli/check.js +6 -6
  41. package/dist/cli/plugins.js +11 -11
  42. package/dist/cli/snapshot-warmup.js +8 -8
  43. package/dist/cli/upgrade.js +5 -5
  44. package/dist/{db-2ASK6MV6.js → db-4VLP7KBF.js} +5 -5
  45. package/dist/instrumentation.js +2 -2
  46. package/dist/nitro.js +2 -2
  47. package/dist/{runner-L363K62Z.js → runner-IPXLWQOF.js} +10 -10
  48. package/dist/{skills-VCPG3NOO.js → skills-QCNZISNF.js} +6 -6
  49. package/dist/{validation-GY7AJBLC.js → validation-I2BW3UHD.js} +6 -6
  50. package/dist/version.js +1 -1
  51. package/package.json +5 -5
@@ -62,6 +62,16 @@ export declare const historyReplacementSchema: z.ZodObject<{
62
62
  type: z.ZodLiteral<"compaction">;
63
63
  modelProfile: z.ZodString;
64
64
  modelId: z.ZodString;
65
+ details: z.ZodOptional<z.ZodObject<{
66
+ reason: z.ZodLiteral<"capacity">;
67
+ estimatedInputTokens: z.ZodNumber;
68
+ replacementInputTokens: z.ZodOptional<z.ZodNumber>;
69
+ triggerTokens: z.ZodNumber;
70
+ inputLimitTokens: z.ZodNumber;
71
+ inputMessageCount: z.ZodNumber;
72
+ retainedMessageCount: z.ZodNumber;
73
+ summaryChars: z.ZodNumber;
74
+ }, z.core.$strict>>;
65
75
  replacementHistory: z.ZodArray<z.ZodObject<{
66
76
  message: z.ZodPipe<z.ZodObject<{
67
77
  role: z.ZodString;
@@ -204,6 +214,24 @@ export declare const conversationEventDataSchema: z.ZodUnion<readonly [z.ZodUnio
204
214
  internal: "internal";
205
215
  scheduler: "scheduler";
206
216
  }>;
217
+ }, z.core.$strict>, z.ZodObject<{
218
+ type: z.ZodLiteral<"turn_routed">;
219
+ turnId: z.ZodString;
220
+ modelProfile: z.ZodString;
221
+ modelId: z.ZodString;
222
+ reasoningLevel: z.ZodEnum<{
223
+ low: "low";
224
+ medium: "medium";
225
+ high: "high";
226
+ xhigh: "xhigh";
227
+ none: "none";
228
+ }>;
229
+ confidence: z.ZodOptional<z.ZodNumber>;
230
+ source: z.ZodEnum<{
231
+ configured: "configured";
232
+ inherited: "inherited";
233
+ router: "router";
234
+ }>;
207
235
  }, z.core.$strict>, z.ZodObject<{
208
236
  type: z.ZodLiteral<"turn_completed">;
209
237
  turnId: z.ZodString;
@@ -275,6 +303,16 @@ export declare const conversationEventDataSchema: z.ZodUnion<readonly [z.ZodUnio
275
303
  type: z.ZodLiteral<"compaction">;
276
304
  modelProfile: z.ZodString;
277
305
  modelId: z.ZodString;
306
+ details: z.ZodOptional<z.ZodObject<{
307
+ reason: z.ZodLiteral<"capacity">;
308
+ estimatedInputTokens: z.ZodNumber;
309
+ replacementInputTokens: z.ZodOptional<z.ZodNumber>;
310
+ triggerTokens: z.ZodNumber;
311
+ inputLimitTokens: z.ZodNumber;
312
+ inputMessageCount: z.ZodNumber;
313
+ retainedMessageCount: z.ZodNumber;
314
+ summaryChars: z.ZodNumber;
315
+ }, z.core.$strict>>;
278
316
  replacementHistory: z.ZodArray<z.ZodObject<{
279
317
  message: z.ZodPipe<z.ZodObject<{
280
318
  role: z.ZodString;
@@ -447,6 +485,24 @@ export declare const conversationEventSchema: z.ZodUnion<readonly [z.ZodObject<{
447
485
  internal: "internal";
448
486
  scheduler: "scheduler";
449
487
  }>;
488
+ }, z.core.$strict>, z.ZodObject<{
489
+ type: z.ZodLiteral<"turn_routed">;
490
+ turnId: z.ZodString;
491
+ modelProfile: z.ZodString;
492
+ modelId: z.ZodString;
493
+ reasoningLevel: z.ZodEnum<{
494
+ low: "low";
495
+ medium: "medium";
496
+ high: "high";
497
+ xhigh: "xhigh";
498
+ none: "none";
499
+ }>;
500
+ confidence: z.ZodOptional<z.ZodNumber>;
501
+ source: z.ZodEnum<{
502
+ configured: "configured";
503
+ inherited: "inherited";
504
+ router: "router";
505
+ }>;
450
506
  }, z.core.$strict>, z.ZodObject<{
451
507
  type: z.ZodLiteral<"turn_completed">;
452
508
  turnId: z.ZodString;
@@ -518,6 +574,16 @@ export declare const conversationEventSchema: z.ZodUnion<readonly [z.ZodObject<{
518
574
  type: z.ZodLiteral<"compaction">;
519
575
  modelProfile: z.ZodString;
520
576
  modelId: z.ZodString;
577
+ details: z.ZodOptional<z.ZodObject<{
578
+ reason: z.ZodLiteral<"capacity">;
579
+ estimatedInputTokens: z.ZodNumber;
580
+ replacementInputTokens: z.ZodOptional<z.ZodNumber>;
581
+ triggerTokens: z.ZodNumber;
582
+ inputLimitTokens: z.ZodNumber;
583
+ inputMessageCount: z.ZodNumber;
584
+ retainedMessageCount: z.ZodNumber;
585
+ summaryChars: z.ZodNumber;
586
+ }, z.core.$strict>>;
521
587
  replacementHistory: z.ZodArray<z.ZodObject<{
522
588
  message: z.ZodPipe<z.ZodObject<{
523
589
  role: z.ZodString;
@@ -717,6 +783,24 @@ export declare const newConversationEventSchema: z.ZodObject<{
717
783
  internal: "internal";
718
784
  scheduler: "scheduler";
719
785
  }>;
786
+ }, z.core.$strict>, z.ZodObject<{
787
+ type: z.ZodLiteral<"turn_routed">;
788
+ turnId: z.ZodString;
789
+ modelProfile: z.ZodString;
790
+ modelId: z.ZodString;
791
+ reasoningLevel: z.ZodEnum<{
792
+ low: "low";
793
+ medium: "medium";
794
+ high: "high";
795
+ xhigh: "xhigh";
796
+ none: "none";
797
+ }>;
798
+ confidence: z.ZodOptional<z.ZodNumber>;
799
+ source: z.ZodEnum<{
800
+ configured: "configured";
801
+ inherited: "inherited";
802
+ router: "router";
803
+ }>;
720
804
  }, z.core.$strict>, z.ZodObject<{
721
805
  type: z.ZodLiteral<"turn_completed">;
722
806
  turnId: z.ZodString;
@@ -759,6 +843,8 @@ export interface ConversationEventStore {
759
843
  append(conversationId: string, events: NewConversationEvent[]): Promise<void>;
760
844
  /** Replace active model history with a compaction or handoff event. */
761
845
  replaceHistory(conversationId: string, replacement: HistoryReplacement): Promise<void>;
846
+ /** One event selected by its retry-stable key across history versions. */
847
+ loadByIdempotencyKey(conversationId: string, idempotencyKey: string): Promise<ConversationEvent | undefined>;
762
848
  /** Events of the current history version in `seq` order. */
763
849
  loadCurrentHistory(conversationId: string): Promise<ConversationEvent[]>;
764
850
  /** Events in the history version containing `seq`, when it exists. */
@@ -1,8 +1,10 @@
1
1
  import { type PiMessage } from "@/chat/pi/messages";
2
2
  import { type ConversationMessageProvenance } from "@/chat/conversations/provenance";
3
- import type { AuthorizationKind } from "@/chat/conversations/history";
3
+ import type { AuthorizationKind, ConversationEvent } from "@/chat/conversations/history";
4
4
  import type { JuniorSqlDatabase } from "@/db/db";
5
5
  import { type PiConversationEventProjection, type PiConversationProjection } from "@/chat/pi/conversation-events";
6
+ import type { ModelProfile } from "@/chat/model-profile";
7
+ import type { TurnReasoningLevel } from "@/chat/reasoning-level";
6
8
  interface ScopedConversation {
7
9
  conversationId: string;
8
10
  }
@@ -77,6 +79,23 @@ export declare function recordAuthorizationCompleted(args: {
77
79
  actorId: string;
78
80
  authorizationId: string;
79
81
  }): Promise<void>;
82
+ /** Load a previously selected execution profile for a resumed turn. */
83
+ export declare function loadTurnRoute(args: {
84
+ conversationId: string;
85
+ turnId: string;
86
+ }): Promise<Extract<ConversationEvent["data"], {
87
+ type: "turn_routed";
88
+ }> | undefined>;
89
+ /** Record the execution profile selected for one turn without changing agent history. */
90
+ export declare function recordTurnRoute(args: {
91
+ conversationId: string;
92
+ turnId: string;
93
+ modelProfile: ModelProfile;
94
+ modelId: string;
95
+ reasoningLevel: TurnReasoningLevel;
96
+ confidence?: number;
97
+ source: "configured" | "inherited" | "router";
98
+ }): Promise<void>;
80
99
  /** Record a host-observed parent tool start without adding it to Pi replay. */
81
100
  export declare function recordToolExecutionStarted(args: {
82
101
  conversationId: string;
@@ -1,14 +1,19 @@
1
1
  export interface ModelContextBudget {
2
2
  contextWindow: number;
3
- maxTokens: number;
4
3
  }
5
4
  /** Estimate text tokens with the shared coarse heuristic used for local budgets. */
6
5
  export declare function estimateTextTokens(text: string): number;
7
6
  /** Derive the automatic compaction threshold from model context capacity. */
8
7
  export declare function calculateContextCompactionTriggerTokens(model: ModelContextBudget): number;
8
+ /** Derive the maximum estimated input size with room for uncounted request overhead. */
9
+ export declare function calculateContextInputLimitTokens(model: ModelContextBudget): number;
9
10
  /** Derive the post-compaction target from the automatic trigger threshold. */
10
11
  export declare function calculateContextCompactionTargetTokens(triggerTokens: number): number;
12
+ /** Cap one model's advertised context capacity with the host bot configuration. */
13
+ export declare function getModelContextBudget(modelId: string): ModelContextBudget;
11
14
  /** Resolve the automatic compaction threshold for the active agent model. */
12
- export declare function getAgentContextCompactionTriggerTokens(): number;
15
+ export declare function getAgentContextCompactionTriggerTokens(modelId: string): number;
16
+ /** Resolve the hard input ceiling for the active agent model. */
17
+ export declare function getAgentContextInputLimitTokens(modelId: string): number;
13
18
  /** Resolve the visible conversation compaction threshold for the auxiliary model. */
14
19
  export declare function getConversationContextCompactionTriggerTokens(): number;
@@ -1,5 +1,6 @@
1
1
  import type { completeText } from "@/chat/pi/client";
2
2
  import type { PiMessage } from "@/chat/pi/messages";
3
+ import { type ConversationMessageProvenance } from "@/chat/conversations/provenance";
3
4
  import type { ThreadConversationState } from "@/chat/state/conversation";
4
5
  import { type ModelProfile } from "@/chat/model-profile";
5
6
  export interface ContextCompactorDeps {
@@ -13,7 +14,7 @@ export interface CompactContextArgs {
13
14
  conversation: ThreadConversationState;
14
15
  conversationContext?: string;
15
16
  conversationId: string;
16
- onCompactionStart?: () => void;
17
+ onCompactionStart?: () => void | Promise<void>;
17
18
  piMessages: PiMessage[];
18
19
  metadata?: {
19
20
  channelId?: string;
@@ -21,6 +22,7 @@ export interface CompactContextArgs {
21
22
  runId?: string;
22
23
  threadId?: string;
23
24
  };
25
+ modelId: string;
24
26
  }
25
27
  export interface CompactContextResult {
26
28
  compacted: boolean;
@@ -41,10 +43,35 @@ interface HandoffContextArgs {
41
43
  reasoningLevel?: string;
42
44
  };
43
45
  }
46
+ interface ActiveContextCompactionArgs {
47
+ conversationContext?: string;
48
+ conversationId: string;
49
+ metadata?: CompactContextArgs["metadata"];
50
+ modelId: string;
51
+ modelProfile: ModelProfile;
52
+ onCompactionStart?: () => void | Promise<void>;
53
+ pendingMessages?: Array<{
54
+ message: PiMessage;
55
+ provenance: ConversationMessageProvenance;
56
+ }>;
57
+ piMessages: PiMessage[];
58
+ signal?: AbortSignal;
59
+ }
60
+ /** Raised when Junior cannot compact history below the active model's hard ceiling. */
61
+ export declare class ContextInputLimitExceededError extends Error {
62
+ readonly estimatedTokens: number;
63
+ readonly inputLimitTokens: number;
64
+ constructor(estimatedTokens: number, inputLimitTokens: number);
65
+ }
44
66
  /** Build retained user messages for a compacted Pi replacement history. */
45
67
  export declare function selectRetainedUserMessages(messages: PiMessage[], maxTokens?: number): PiMessage[];
46
68
  /** Build the service that owns local context compaction. */
47
69
  export declare function createContextCompactor(deps: ContextCompactorDeps): ContextCompactor;
48
70
  /** Compact the active conversation and durably bind its selected handoff profile. */
49
71
  export declare function compactContextForHandoff(args: HandoffContextArgs, deps: Pick<ContextCompactorDeps, "completeText">): Promise<PiMessage[]>;
72
+ /**
73
+ * Replace oversized active history at Pi's next-turn boundary before another
74
+ * provider request can observe it.
75
+ */
76
+ export declare function compactActiveContextIfNeeded(args: ActiveContextCompactionArgs, deps: Pick<ContextCompactorDeps, "completeText">): Promise<CompactContextResult>;
50
77
  export {};
@@ -14,6 +14,7 @@ export interface ConversationMemoryService {
14
14
  generateThreadTitle: (sourceText: string) => Promise<string>;
15
15
  }
16
16
  export declare function generateConversationId(prefix: "assistant" | "backfill" | "compaction" | "turn"): string;
17
+ /** Normalize message boundaries without changing transcript formatting. */
17
18
  export declare function normalizeConversationText(text: string): string;
18
19
  export declare function updateConversationStats(conversation: ThreadConversationState): void;
19
20
  export declare function upsertConversationMessage(conversation: ThreadConversationState, message: ConversationMessage): string;
@@ -12,6 +12,7 @@ interface ProviderErrorOptions {
12
12
  retryable?: boolean;
13
13
  }
14
14
  interface ProviderErrorDetails {
15
+ cause?: unknown;
15
16
  kind: ProviderErrorKind;
16
17
  modelId?: string;
17
18
  retryable: boolean;
@@ -20,6 +20,7 @@ export interface TurnRoute {
20
20
  profile: ModelProfile;
21
21
  reasoningLevel: TurnReasoningLevel;
22
22
  reason: string;
23
+ source?: "configured" | "inherited" | "router";
23
24
  }
24
25
  /** Preserve an explicitly configured reasoning level without invoking the router. */
25
26
  export declare function configuredTurnRoute(profile: ModelProfile, reasoningLevel: TurnReasoningLevel, source: "agent_config" | "default" | "profile"): TurnRoute;
@@ -9,7 +9,6 @@ interface EditFileResult {
9
9
  }];
10
10
  details: {
11
11
  data: {
12
- diff: string;
13
12
  first_changed_line?: number;
14
13
  path: string;
15
14
  replacements: number;
@@ -21,6 +20,7 @@ interface EditFileResult {
21
20
  replacements: number;
22
21
  status: "success";
23
22
  target: string;
23
+ truncated: boolean;
24
24
  } | {
25
25
  data: {
26
26
  path: string;
@@ -20,6 +20,7 @@ export declare function prepareTextReplacementArguments<T extends TextReplacemen
20
20
  export declare function buildCompactDiff(oldContent: string, newContent: string): {
21
21
  diff: string;
22
22
  firstChangedLine?: number;
23
+ truncated: boolean;
23
24
  };
24
25
  /** Apply exact replacements to normalized text after validating uniqueness and overlap. */
25
26
  export declare function validateAndApplyTextEdits(content: string, edits: TextReplacement[], targetName: string): {
@@ -13,7 +13,7 @@ import {
13
13
  } from "./chunk-6GWA276C.js";
14
14
  import {
15
15
  getDeploymentTelemetryAttributes
16
- } from "./chunk-NP7TYFYR.js";
16
+ } from "./chunk-5CZ7RETL.js";
17
17
 
18
18
  // src/chat/logging.ts
19
19
  import path from "path";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  JUNIOR_VERSION
3
- } from "./chunk-ZRSUCJGA.js";
3
+ } from "./chunk-PM3PX42K.js";
4
4
 
5
5
  // src/deployment.ts
6
6
  var JUNIOR_HEARTBEAT_ROUTE = "/api/internal/heartbeat";
@@ -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-YU6PO42Q.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-FIGAF6KL.js";
19
19
  import {
20
20
  sleep
21
21
  } from "./chunk-4ZNGQH7C.js";
@@ -23,9 +23,8 @@ import {
23
23
  botConfig,
24
24
  escapeXml,
25
25
  resolveGatewayModel,
26
- standardModelId,
27
26
  unwrapCurrentInstruction
28
- } from "./chunk-RCBUZGIT.js";
27
+ } from "./chunk-ZGXH3REA.js";
29
28
  import {
30
29
  toStoredSlackActor
31
30
  } from "./chunk-C4MZ3GP5.js";
@@ -34,7 +33,7 @@ import {
34
33
  logException,
35
34
  logWarn,
36
35
  setSpanAttributes
37
- } from "./chunk-36UJA3OD.js";
36
+ } from "./chunk-4FUEG3QY.js";
38
37
  import {
39
38
  isRecord,
40
39
  parseSlackMessageTs,
@@ -451,6 +450,36 @@ async function recordAuthorizationCompleted(args) {
451
450
  }
452
451
  ]);
453
452
  }
453
+ async function loadTurnRoute(args) {
454
+ const event = await getConversationEventStore().loadByIdempotencyKey(
455
+ args.conversationId,
456
+ `turn:${args.turnId}:routed`
457
+ );
458
+ if (!event) {
459
+ return void 0;
460
+ }
461
+ if (event.data.type !== "turn_routed" || event.data.turnId !== args.turnId) {
462
+ throw new Error(`Turn route key for "${args.turnId}" has invalid data`);
463
+ }
464
+ return event.data;
465
+ }
466
+ async function recordTurnRoute(args) {
467
+ await getConversationEventStore().append(args.conversationId, [
468
+ {
469
+ idempotencyKey: `turn:${args.turnId}:routed`,
470
+ createdAtMs: Date.now(),
471
+ data: {
472
+ type: "turn_routed",
473
+ turnId: args.turnId,
474
+ modelProfile: args.modelProfile,
475
+ modelId: args.modelId,
476
+ reasoningLevel: args.reasoningLevel,
477
+ ...args.confidence !== void 0 ? { confidence: args.confidence } : {},
478
+ source: args.source
479
+ }
480
+ }
481
+ ]);
482
+ }
454
483
  async function recordToolExecutionStarted(args) {
455
484
  await getConversationEventStore().append(args.conversationId, [
456
485
  {
@@ -1588,11 +1617,10 @@ function buildConversationStatePatch(conversation) {
1588
1617
  }
1589
1618
 
1590
1619
  // src/chat/services/context-budget.ts
1591
- var COMPACTION_TRIGGER_INPUT_RATIO = 0.75;
1592
- var COMPACTION_OUTPUT_RESERVE_RATIO = 0.25;
1620
+ var COMPACTION_TRIGGER_RATIO = 0.9;
1621
+ var CONTEXT_INPUT_LIMIT_RATIO = 0.95;
1593
1622
  var COMPACTION_TARGET_RATIO = 0.8;
1594
1623
  var FALLBACK_CONTEXT_WINDOW_TOKENS = 4e5;
1595
- var FALLBACK_MAX_OUTPUT_TOKENS = 128e3;
1596
1624
  function positiveInteger(value, fallback) {
1597
1625
  return Number.isFinite(value) && value > 0 ? Math.floor(value) : fallback;
1598
1626
  }
@@ -1604,36 +1632,43 @@ function calculateContextCompactionTriggerTokens(model) {
1604
1632
  model.contextWindow,
1605
1633
  FALLBACK_CONTEXT_WINDOW_TOKENS
1606
1634
  );
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)
1635
+ return Math.max(1, Math.floor(contextWindow * COMPACTION_TRIGGER_RATIO));
1636
+ }
1637
+ function calculateContextInputLimitTokens(model) {
1638
+ const contextWindow = positiveInteger(
1639
+ model.contextWindow,
1640
+ FALLBACK_CONTEXT_WINDOW_TOKENS
1619
1641
  );
1642
+ return Math.max(1, Math.floor(contextWindow * CONTEXT_INPUT_LIMIT_RATIO));
1620
1643
  }
1621
1644
  function calculateContextCompactionTargetTokens(triggerTokens) {
1622
1645
  return Math.max(1, Math.floor(triggerTokens * COMPACTION_TARGET_RATIO));
1623
1646
  }
1624
- function getAgentContextCompactionTriggerTokens() {
1625
- const model = resolveGatewayModel(standardModelId(botConfig));
1626
- return calculateContextCompactionTriggerTokens({
1627
- contextWindow: botConfig.modelContextWindowTokens ?? model.contextWindow,
1628
- maxTokens: model.maxTokens
1629
- });
1647
+ function getModelContextBudget(modelId) {
1648
+ const model = resolveGatewayModel(modelId);
1649
+ const advertisedContextWindow = positiveInteger(
1650
+ model.contextWindow,
1651
+ FALLBACK_CONTEXT_WINDOW_TOKENS
1652
+ );
1653
+ return {
1654
+ contextWindow: Math.min(
1655
+ botConfig.contextWindowTokens,
1656
+ advertisedContextWindow
1657
+ )
1658
+ };
1659
+ }
1660
+ function getAgentContextCompactionTriggerTokens(modelId) {
1661
+ return calculateContextCompactionTriggerTokens(
1662
+ getModelContextBudget(modelId)
1663
+ );
1664
+ }
1665
+ function getAgentContextInputLimitTokens(modelId) {
1666
+ return calculateContextInputLimitTokens(getModelContextBudget(modelId));
1630
1667
  }
1631
1668
  function getConversationContextCompactionTriggerTokens() {
1632
- const model = resolveGatewayModel(botConfig.fastModelId);
1633
- return calculateContextCompactionTriggerTokens({
1634
- contextWindow: model.contextWindow,
1635
- maxTokens: model.maxTokens
1636
- });
1669
+ return calculateContextCompactionTriggerTokens(
1670
+ getModelContextBudget(botConfig.fastModelId)
1671
+ );
1637
1672
  }
1638
1673
 
1639
1674
  // src/chat/services/conversation-memory.ts
@@ -1646,7 +1681,7 @@ function generateConversationId(prefix) {
1646
1681
  return `${prefix}_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;
1647
1682
  }
1648
1683
  function normalizeConversationText(text) {
1649
- return text.trim().replace(/\s+/g, " ").slice(0, CONTEXT_MAX_MESSAGE_CHARS);
1684
+ return text.replace(/\r\n?/g, "\n").trim();
1650
1685
  }
1651
1686
  function buildImageContextSuffix(message, conversation) {
1652
1687
  const byFileId = conversation?.vision.byFileId;
@@ -1662,6 +1697,7 @@ function buildImageContextSuffix(message, conversation) {
1662
1697
  }
1663
1698
  function renderConversationMessageLine(message, conversation) {
1664
1699
  const displayName = conversationAuthorDisplayName(message);
1700
+ const text = message.text.replace(/\s+/g, " ").slice(0, CONTEXT_MAX_MESSAGE_CHARS);
1665
1701
  const markers = [];
1666
1702
  if (message.meta?.replied === false) {
1667
1703
  markers.push(
@@ -1673,7 +1709,7 @@ function renderConversationMessageLine(message, conversation) {
1673
1709
  }
1674
1710
  const markerSuffix = markers.length > 0 ? ` (${markers.join("; ")})` : "";
1675
1711
  const imageContext = buildImageContextSuffix(message, conversation);
1676
- return `[${message.role}] ${displayName}: ${message.text}${imageContext}${markerSuffix}`;
1712
+ return `[${message.role}] ${displayName}: ${text}${imageContext}${markerSuffix}`;
1677
1713
  }
1678
1714
  function conversationAuthorDisplayName(message) {
1679
1715
  const author = message.author;
@@ -2650,6 +2686,8 @@ export {
2650
2686
  recordMcpProviderConnected,
2651
2687
  recordAuthorizationRequested,
2652
2688
  recordAuthorizationCompleted,
2689
+ loadTurnRoute,
2690
+ recordTurnRoute,
2653
2691
  recordToolExecutionStarted,
2654
2692
  buildDeterministicTurnId,
2655
2693
  buildDeterministicAssistantMessageId,
@@ -2692,6 +2730,7 @@ export {
2692
2730
  persistConversationMessageSummaries,
2693
2731
  estimateTextTokens,
2694
2732
  getAgentContextCompactionTriggerTokens,
2733
+ getAgentContextInputLimitTokens,
2695
2734
  normalizeConversationText,
2696
2735
  updateConversationStats,
2697
2736
  upsertConversationMessage,
@@ -20,28 +20,28 @@ import {
20
20
  normalizeToolNameFromResult,
21
21
  stripRuntimeTurnContext,
22
22
  updateConversationStats
23
- } from "./chunk-DXRPHBOU.js";
23
+ } from "./chunk-6QWPVTMO.js";
24
24
  import {
25
25
  createPluginEmbedder,
26
26
  createPluginLogger,
27
27
  createPluginModel,
28
28
  createPluginState,
29
29
  getPlugins
30
- } from "./chunk-YJ44UT7D.js";
30
+ } from "./chunk-VNNBSKCO.js";
31
31
  import {
32
32
  getStateAdapter
33
- } from "./chunk-HMRVILWZ.js";
33
+ } from "./chunk-YU6PO42Q.js";
34
34
  import {
35
35
  getDb
36
- } from "./chunk-LLKDNPYV.js";
36
+ } from "./chunk-FIGAF6KL.js";
37
37
  import {
38
38
  ProviderError,
39
39
  getProviderErrorAttributes,
40
40
  getProviderErrorUserMessage
41
- } from "./chunk-RCBUZGIT.js";
41
+ } from "./chunk-ZGXH3REA.js";
42
42
  import {
43
43
  buildTurnFailureResponse
44
- } from "./chunk-36UJA3OD.js";
44
+ } from "./chunk-4FUEG3QY.js";
45
45
  import {
46
46
  parseSlackMessageTs
47
47
  } from "./chunk-42WRQLJ6.js";
@@ -6,15 +6,16 @@ import {
6
6
  juniorUsers
7
7
  } from "./chunk-JQFJO5WH.js";
8
8
  import {
9
+ TURN_REASONING_LEVELS,
9
10
  getChatConfig,
10
11
  modelProfileSchema
11
- } from "./chunk-RCBUZGIT.js";
12
+ } from "./chunk-ZGXH3REA.js";
12
13
  import {
13
14
  juniorDestinations
14
15
  } from "./chunk-VFUK3X5B.js";
15
16
  import {
16
17
  normalizeIdentityEmail
17
- } from "./chunk-36UJA3OD.js";
18
+ } from "./chunk-4FUEG3QY.js";
18
19
  import {
19
20
  parseSlackChannelReferenceId,
20
21
  parseSlackTeamId
@@ -809,6 +810,16 @@ var replacementHistoryMessageSchema = conversationMessageDataSchema.extend({
809
810
  sourceEventSeq: z2.number().int().nonnegative().optional()
810
811
  });
811
812
  var replacementHistorySchema = z2.array(replacementHistoryMessageSchema);
813
+ var compactionDetailsSchema = z2.object({
814
+ reason: z2.literal("capacity"),
815
+ estimatedInputTokens: z2.number().int().nonnegative(),
816
+ replacementInputTokens: z2.number().int().nonnegative().optional(),
817
+ triggerTokens: z2.number().int().nonnegative(),
818
+ inputLimitTokens: z2.number().int().positive(),
819
+ inputMessageCount: z2.number().int().nonnegative(),
820
+ retainedMessageCount: z2.number().int().nonnegative(),
821
+ summaryChars: z2.number().int().nonnegative()
822
+ }).strict();
812
823
  var historyReplacementEventDataSchema = z2.discriminatedUnion("type", [
813
824
  z2.object({
814
825
  type: z2.literal("handoff"),
@@ -822,6 +833,7 @@ var historyReplacementEventDataSchema = z2.discriminatedUnion("type", [
822
833
  type: z2.literal("compaction"),
823
834
  modelProfile: modelProfileSchema,
824
835
  modelId: z2.string().min(1),
836
+ details: compactionDetailsSchema.optional(),
825
837
  replacementHistory: replacementHistorySchema
826
838
  }).strict()
827
839
  ]);
@@ -919,6 +931,15 @@ var turnStartedEventDataSchema = z2.object({
919
931
  (data) => new Set(data.inputMessageIds).size === data.inputMessageIds.length,
920
932
  "turn input message ids must be unique"
921
933
  );
934
+ var turnRoutedEventDataSchema = z2.object({
935
+ type: z2.literal("turn_routed"),
936
+ turnId: z2.string().min(1),
937
+ modelProfile: modelProfileSchema,
938
+ modelId: z2.string().min(1),
939
+ reasoningLevel: z2.enum(TURN_REASONING_LEVELS),
940
+ confidence: z2.number().min(0).max(1).optional(),
941
+ source: z2.enum(["configured", "inherited", "router"])
942
+ }).strict();
922
943
  var turnCompletedEventDataSchema = z2.object({
923
944
  type: z2.literal("turn_completed"),
924
945
  turnId: z2.string().min(1),
@@ -960,6 +981,7 @@ var appendableConversationEventDataSchema = z2.union([
960
981
  messageHandledEventDataSchema,
961
982
  messagesSummarizedEventDataSchema,
962
983
  turnStartedEventDataSchema,
984
+ turnRoutedEventDataSchema,
963
985
  turnCompletedEventDataSchema,
964
986
  turnFailedEventDataSchema,
965
987
  subagentStartedEventDataSchema,
@@ -981,6 +1003,7 @@ var knownConversationEventTypeSchema = z2.enum([
981
1003
  "message_handled",
982
1004
  "messages_summarized",
983
1005
  "turn_started",
1006
+ "turn_routed",
984
1007
  "turn_completed",
985
1008
  "turn_failed",
986
1009
  "subagent_started",
@@ -1219,6 +1242,15 @@ var SqlConversationEventStore = class {
1219
1242
  ).orderBy(asc2(juniorConversationEvents.seq));
1220
1243
  return rows.map(eventFromRow);
1221
1244
  }
1245
+ async loadByIdempotencyKey(conversationId, idempotencyKey) {
1246
+ const [row] = await this.executor.db().select().from(juniorConversationEvents).where(
1247
+ and3(
1248
+ eq3(juniorConversationEvents.conversationId, conversationId),
1249
+ eq3(juniorConversationEvents.idempotencyKey, idempotencyKey)
1250
+ )
1251
+ ).limit(1);
1252
+ return row ? eventFromRow(row) : void 0;
1253
+ }
1222
1254
  async loadHistoryContaining(conversationId, seq, throughSeq) {
1223
1255
  const [boundary] = await this.executor.db().select({ historyVersion: juniorConversationEvents.historyVersion }).from(juniorConversationEvents).where(
1224
1256
  and3(
@@ -5,7 +5,7 @@ import {
5
5
  logInfo,
6
6
  logWarn,
7
7
  setSpanAttributes
8
- } from "./chunk-36UJA3OD.js";
8
+ } from "./chunk-4FUEG3QY.js";
9
9
  import {
10
10
  discoverInstalledPluginPackageContent,
11
11
  normalizePluginPackageNames
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-2ZTTXTSZ.js";
4
4
  import {
5
5
  normalizeSlackConversationId
6
- } from "./chunk-QTS66GMR.js";
6
+ } from "./chunk-RD7EJI7H.js";
7
7
  import {
8
8
  parseSlackThreadId
9
9
  } from "./chunk-6Y5L4BOM.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createPluginCatalogRuntime
3
- } from "./chunk-OXE5ZUTS.js";
3
+ } from "./chunk-K2W4CK7K.js";
4
4
 
5
5
  // src/chat/plugins/catalog-runtime.ts
6
6
  var pluginCatalogRuntime = createPluginCatalogRuntime();