n8n 2.32.3 → 2.32.5

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.
@@ -177,6 +177,7 @@ function getAbortReason(signal) {
177
177
  return typeof reason === 'string' ? reason : 'user_cancelled';
178
178
  }
179
179
  const MAX_CONCURRENT_BACKGROUND_TASKS_PER_THREAD = 5;
180
+ const MAX_CONSECUTIVE_FAILED_INTERNAL_FOLLOW_UPS = 3;
180
181
  const TITLE_REFINE_HISTORY_LIMIT = 50;
181
182
  function toConfirmationData(request) {
182
183
  switch (request.kind) {
@@ -256,6 +257,7 @@ let InstanceAiService = class InstanceAiService {
256
257
  this.threadPushRef = new Map();
257
258
  this.planRequestsByThread = new Map();
258
259
  this.schedulerLocks = new Map();
260
+ this.failedInternalFollowUpStreaks = new Map();
259
261
  this.pendingCheckpointReentries = new Map();
260
262
  this.runDebugBuffer = new instance_ai_1.RunDebugBuffer();
261
263
  this.checkpointPruningStopped = true;
@@ -842,6 +844,7 @@ let InstanceAiService = class InstanceAiService {
842
844
  metadata: { completion_source: 'service_cleanup' },
843
845
  });
844
846
  this.schedulerLocks.delete(threadId);
847
+ this.failedInternalFollowUpStreaks.delete(threadId);
845
848
  this.domainAccessTrackersByThread.delete(threadId);
846
849
  this.evalCredentialAllowlists.clearThread(threadId);
847
850
  this.threadPushRef.delete(threadId);
@@ -1222,6 +1225,9 @@ let InstanceAiService = class InstanceAiService {
1222
1225
  const localGatewayDisabledForUser = await this.settingsService.isLocalGatewayDisabledForUser(user.id);
1223
1226
  const userGateway = this.gatewayService.findGateway(user.id);
1224
1227
  const { searchProxyConfig, tracingProxyConfig, tokenManager, proxyBaseUrl } = proxyRunConfig ?? (await this.createProxyRunConfig(user));
1228
+ const modelId = proxyBaseUrl && tokenManager
1229
+ ? await this.modelService.resolveProxyModel(user, proxyBaseUrl, tokenManager)
1230
+ : await this.modelService.resolveAgentModelConfig(user);
1225
1231
  const configEvalsEnabled = await this.adapterService.isConfigEvalsEnabled(user);
1226
1232
  const context = this.adapterService.createContext(user, {
1227
1233
  searchProxyConfig,
@@ -1230,6 +1236,7 @@ let InstanceAiService = class InstanceAiService {
1230
1236
  projectId: boundProjectId,
1231
1237
  credentialIdAllowlist: this.evalCredentialAllowlists.get(threadId),
1232
1238
  configEvalsEnabled,
1239
+ modelId,
1233
1240
  });
1234
1241
  this.gatewayService.applyToolPolicy(user.id);
1235
1242
  const gatewayMcpServer = !localGatewayDisabledForUser && userGateway?.isConnected ? userGateway : undefined;
@@ -1295,9 +1302,6 @@ let InstanceAiService = class InstanceAiService {
1295
1302
  status: localGatewayDisabledForUser ? 'disabled' : 'disconnected',
1296
1303
  };
1297
1304
  }
1298
- const modelId = proxyBaseUrl && tokenManager
1299
- ? await this.modelService.resolveProxyModel(user, proxyBaseUrl, tokenManager)
1300
- : await this.modelService.resolveAgentModelConfig(user);
1301
1305
  const taskStorage = new instance_ai_1.ThreadTaskStorage(memory);
1302
1306
  const iterationLog = this.dbIterationLogStorage;
1303
1307
  const snapshotStorage = this.dbSnapshotStorage;
@@ -1778,11 +1782,29 @@ let InstanceAiService = class InstanceAiService {
1778
1782
  async releaseWorkItemSetupRoutingClaim(threadId, workItemId, claimId) {
1779
1783
  await new instance_ai_1.WorkflowLoopStorage(this.agentMemory).releaseSetupRoutingClaim(threadId, workItemId, claimId);
1780
1784
  }
1785
+ updateInternalFollowUpFailureStreak(threadId, status, isInternalFollowUp) {
1786
+ if (status === 'completed' || status === 'suspended') {
1787
+ this.failedInternalFollowUpStreaks.delete(threadId);
1788
+ return;
1789
+ }
1790
+ if (status === 'error' && isInternalFollowUp) {
1791
+ this.failedInternalFollowUpStreaks.set(threadId, (this.failedInternalFollowUpStreaks.get(threadId) ?? 0) + 1);
1792
+ }
1793
+ }
1781
1794
  async startInternalFollowUpRun(user, threadId, message, messageGroupId, isReplanFollowUp = false, checkpoint, resumeReasonOverride, plannedBuild) {
1782
1795
  if (this.runState.hasLiveRun(threadId)) {
1783
1796
  this.logger.warn('Skipping internal follow-up: active run exists', { threadId });
1784
1797
  return '';
1785
1798
  }
1799
+ const failedStreak = this.failedInternalFollowUpStreaks.get(threadId) ?? 0;
1800
+ if (failedStreak >= MAX_CONSECUTIVE_FAILED_INTERNAL_FOLLOW_UPS) {
1801
+ this.logger.warn('Skipping internal follow-up: consecutive follow-up runs keep failing', {
1802
+ threadId,
1803
+ failedStreak,
1804
+ resumeReason: resumeReasonOverride,
1805
+ });
1806
+ return '';
1807
+ }
1786
1808
  const { runId, abortController } = this.runState.startRun({
1787
1809
  threadId,
1788
1810
  user,
@@ -2538,6 +2560,7 @@ let InstanceAiService = class InstanceAiService {
2538
2560
  this.liveness.consumeRunTimeout(runId);
2539
2561
  }
2540
2562
  }
2563
+ this.updateInternalFollowUpFailureStreak(threadId, messageTraceFinalization?.status, resumeReason !== undefined);
2541
2564
  if (!this.runState.hasSuspendedRun(threadId)) {
2542
2565
  if (checkpoint?.isCheckpointFollowUp) {
2543
2566
  await this.finalizeCheckpointFollowUp(user, threadId, checkpoint.checkpointTaskId);
@@ -3281,6 +3304,7 @@ let InstanceAiService = class InstanceAiService {
3281
3304
  this.liveness.consumeRunTimeout(opts.runId);
3282
3305
  }
3283
3306
  }
3307
+ this.updateInternalFollowUpFailureStreak(opts.threadId, messageTraceFinalization?.status, false);
3284
3308
  if (!this.runState.hasSuspendedRun(opts.threadId)) {
3285
3309
  if (opts.checkpoint?.isCheckpointFollowUp) {
3286
3310
  await this.finalizeCheckpointFollowUp(opts.user, opts.threadId, opts.checkpoint.checkpointTaskId);