@trigger.dev/sdk 4.6.2 → 4.6.4

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.
@@ -415,6 +415,8 @@ export type ChatNewToolResult = {
415
415
  interface CompactionState {
416
416
  summary: string;
417
417
  baseResponseMessageCount: number;
418
+ /** Completed steps summarized this turn; unlike message counts, matches UI step markers. */
419
+ baseResponseStepCount: number;
418
420
  }
419
421
  /**
420
422
  * Event passed to `summarize` callbacks.
@@ -1454,13 +1456,17 @@ export type TurnCompleteEvent<TClientData = unknown, TUIM extends UIMessage = UI
1454
1456
  */
1455
1457
  uiMessages: TUIM[];
1456
1458
  /**
1457
- * Only the new model messages from this turn (user message(s) + assistant response).
1458
- * Useful for appending to an existing conversation record.
1459
+ * Model messages for this turn's user message(s) and complete assistant response,
1460
+ * including steps summarized during the turn. Same-ID approval and handover
1461
+ * continuations include the full replacement response, so these are not always
1462
+ * an append-only delta. Persist `messages` for future model context, or upsert
1463
+ * `newUIMessages` by ID for the visible conversation.
1459
1464
  */
1460
1465
  newMessages: ModelMessage[];
1461
1466
  /**
1462
- * Only the new UI messages from this turn (user message(s) + assistant response).
1463
- * Useful for inserting individual message records instead of overwriting the full history.
1467
+ * New or updated UI messages from this turn (user message(s) + assistant response).
1468
+ * Upsert by message ID: approval and handover continuations can replace an
1469
+ * existing assistant message.
1464
1470
  */
1465
1471
  newUIMessages: TUIM[];
1466
1472
  /** The assistant's response for this turn, with aborted parts cleaned up when `stopped` is true. Undefined if `pipeChat` was used manually. */
@@ -18,6 +18,7 @@ const api_1 = require("@opentelemetry/api");
18
18
  const sessionTracing_js_1 = require("./sessionTracing.js");
19
19
  const ai_runtime_js_1 = require("../imports/ai-runtime.js");
20
20
  const transcriptStorage_js_1 = require("./transcriptStorage.js");
21
+ const compactionResponse_js_1 = require("./compactionResponse.js");
21
22
  let transcriptStorageOverride;
22
23
  /**
23
24
  * Test-only override for the storage `chat.agent` persists through, so a
@@ -2803,6 +2804,7 @@ async function chatCompact(messages, steps, options) {
2803
2804
  locals_js_1.locals.set(chatCompactionStateKey, {
2804
2805
  summary,
2805
2806
  baseResponseMessageCount: currentStep.response.messages.length,
2807
+ baseResponseStepCount: steps.length,
2806
2808
  });
2807
2809
  // Set model-only override — UI messages stay intact for persistence.
2808
2810
  // The summary becomes the model message history for the next turn,
@@ -5912,6 +5914,13 @@ function chatAgent(options) {
5912
5914
  // Check if compaction set a model-only override (preserves UI messages).
5913
5915
  // Apply compactUIMessages/compactModelMessages callbacks if configured.
5914
5916
  const modelOnlyOverride = locals_js_1.locals.get(chatOverrideModelMessagesKey);
5917
+ const responseCompaction = modelOnlyOverride
5918
+ ? locals_js_1.locals.get(chatCompactionStateKey)
5919
+ : undefined;
5920
+ // Capture the original assistant before compactUIMessages can remove it.
5921
+ const originalResponse = responseCompaction && capturedResponseMessage
5922
+ ? accumulatedUIMessages.find((m) => m.id === capturedResponseMessage?.id)
5923
+ : undefined;
5915
5924
  if (modelOnlyOverride) {
5916
5925
  const compactionSummary = locals_js_1.locals.get(chatCompactionStateKey)?.summary ?? "";
5917
5926
  const taskCompactionConfig = locals_js_1.locals.get(chatAgentCompactionKey);
@@ -6003,10 +6012,31 @@ function chatAgent(options) {
6003
6012
  // rationale (TRI-9137).
6004
6013
  recordToolCallIdsFromMessage(capturedResponseMessage);
6005
6014
  try {
6015
+ const responseForModel = (0, compactionResponse_js_1.responseAfterCompaction)(capturedResponseMessage, responseCompaction?.baseResponseStepCount, originalResponse);
6016
+ // Preserve the complete persistence response, including same-ID
6017
+ // replacements whose old tool parts can contain new results.
6018
+ // Convert prefix and suffix separately so each tool output is
6019
+ // converted once, while only the suffix enters model context.
6020
+ const responsePrefixMessages = responseCompaction
6021
+ ? await toModelMessages([
6022
+ stripProviderMetadata({
6023
+ ...capturedResponseMessage,
6024
+ parts: capturedResponseMessage.parts.slice(0, capturedResponseMessage.parts.length -
6025
+ responseForModel.parts.length),
6026
+ }),
6027
+ ])
6028
+ : [];
6006
6029
  const responseModelMessages = await toModelMessages([
6007
- stripProviderMetadata(capturedResponseMessage),
6030
+ stripProviderMetadata(responseForModel),
6008
6031
  ]);
6009
- if (existingIdx !== -1) {
6032
+ if (responseCompaction) {
6033
+ // The summary already replaced the original response, including
6034
+ // a same-ID approval/handover prefix. Replacing its old model run
6035
+ // would miss and fall back to the full, uncompacted UI history.
6036
+ accumulatedMessages.push(...responseModelMessages);
6037
+ locals_js_1.locals.set(chatHandoverSplicedRunKey, undefined);
6038
+ }
6039
+ else if (existingIdx !== -1) {
6010
6040
  const spliced = locals_js_1.locals.get(chatHandoverSplicedRunKey);
6011
6041
  const splicedRun = spliced && previousAtIdx && spliced.id === previousAtIdx.id
6012
6042
  ? spliced.run
@@ -6025,7 +6055,7 @@ function chatAgent(options) {
6025
6055
  else {
6026
6056
  accumulatedMessages.push(...responseModelMessages);
6027
6057
  }
6028
- turnNewModelMessages.push(...responseModelMessages);
6058
+ turnNewModelMessages.push(...responsePrefixMessages, ...responseModelMessages);
6029
6059
  }
6030
6060
  catch {
6031
6061
  // Conversion failed — skip accumulation for this turn