n8n 2.19.2 → 2.20.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 (306) hide show
  1. package/dist/build.tsbuildinfo +1 -1
  2. package/dist/chat/chat-execution-manager.js +7 -1
  3. package/dist/chat/chat-execution-manager.js.map +1 -1
  4. package/dist/collaboration/collaboration.service.d.ts +1 -0
  5. package/dist/collaboration/collaboration.service.js +31 -0
  6. package/dist/collaboration/collaboration.service.js.map +1 -1
  7. package/dist/commands/execute.d.ts +2 -2
  8. package/dist/commands/export/credentials.d.ts +2 -2
  9. package/dist/commands/export/credentials.js +1 -1
  10. package/dist/commands/export/credentials.js.map +1 -1
  11. package/dist/commands/export/workflow.d.ts +4 -4
  12. package/dist/commands/import/credentials.d.ts +12 -2
  13. package/dist/commands/import/credentials.js +89 -11
  14. package/dist/commands/import/credentials.js.map +1 -1
  15. package/dist/commands/import/workflow.d.ts +2 -2
  16. package/dist/commands/ttwf/generate.d.ts +3 -3
  17. package/dist/controllers/e2e.controller.js +1 -1
  18. package/dist/controllers/e2e.controller.js.map +1 -1
  19. package/dist/controllers/oauth/oauth2-credential.controller.d.ts +6 -4
  20. package/dist/controllers/oauth/oauth2-credential.controller.js +12 -5
  21. package/dist/controllers/oauth/oauth2-credential.controller.js.map +1 -1
  22. package/dist/credentials/credentials.controller.js +1 -1
  23. package/dist/credentials/credentials.controller.js.map +1 -1
  24. package/dist/credentials/credentials.service.d.ts +2 -2
  25. package/dist/credentials/credentials.service.ee.js +2 -2
  26. package/dist/credentials/credentials.service.ee.js.map +1 -1
  27. package/dist/credentials/credentials.service.js +13 -16
  28. package/dist/credentials/credentials.service.js.map +1 -1
  29. package/dist/credentials/dynamic-credentials-proxy.js +1 -1
  30. package/dist/credentials/dynamic-credentials-proxy.js.map +1 -1
  31. package/dist/credentials-helper.d.ts +1 -0
  32. package/dist/credentials-helper.js +12 -4
  33. package/dist/credentials-helper.js.map +1 -1
  34. package/dist/credentials-overwrites.js +2 -2
  35. package/dist/credentials-overwrites.js.map +1 -1
  36. package/dist/evaluation.ee/test-runner/evaluation-metrics.ee.d.ts +5 -0
  37. package/dist/evaluation.ee/test-runner/evaluation-metrics.ee.js +22 -12
  38. package/dist/evaluation.ee/test-runner/evaluation-metrics.ee.js.map +1 -1
  39. package/dist/evaluation.ee/test-runner/test-runner.service.ee.d.ts +4 -2
  40. package/dist/evaluation.ee/test-runner/test-runner.service.ee.js +152 -89
  41. package/dist/evaluation.ee/test-runner/test-runner.service.ee.js.map +1 -1
  42. package/dist/evaluation.ee/test-runs.controller.ee.d.ts +8 -2
  43. package/dist/evaluation.ee/test-runs.controller.ee.js +31 -5
  44. package/dist/evaluation.ee/test-runs.controller.ee.js.map +1 -1
  45. package/dist/eventbus/event-message-classes/index.d.ts +3 -2
  46. package/dist/eventbus/event-message-classes/index.js +11 -1
  47. package/dist/eventbus/event-message-classes/index.js.map +1 -1
  48. package/dist/eventbus/message-event-bus/message-event-bus.d.ts +5 -2
  49. package/dist/eventbus/message-event-bus/message-event-bus.js +101 -73
  50. package/dist/eventbus/message-event-bus/message-event-bus.js.map +1 -1
  51. package/dist/eventbus/message-event-bus-writer/message-event-bus-log-writer.d.ts +3 -0
  52. package/dist/eventbus/message-event-bus-writer/message-event-bus-log-writer.js +3 -1
  53. package/dist/eventbus/message-event-bus-writer/message-event-bus-log-writer.js.map +1 -1
  54. package/dist/eventbus/message-event-bus-writer/resolve-event-log-path.d.ts +12 -0
  55. package/dist/eventbus/message-event-bus-writer/resolve-event-log-path.js +34 -0
  56. package/dist/eventbus/message-event-bus-writer/resolve-event-log-path.js.map +1 -0
  57. package/dist/execution-lifecycle/execute-error-workflow.js +1 -1
  58. package/dist/execution-lifecycle/execute-error-workflow.js.map +1 -1
  59. package/dist/executions/execution-recovery.service.d.ts +1 -1
  60. package/dist/executions/execution-recovery.service.js +11 -6
  61. package/dist/executions/execution-recovery.service.js.map +1 -1
  62. package/dist/executions/execution.service.d.ts +7 -2
  63. package/dist/executions/execution.service.js +18 -1
  64. package/dist/executions/execution.service.js.map +1 -1
  65. package/dist/executions/executions.controller.d.ts +1 -3
  66. package/dist/executions/executions.controller.js +3 -17
  67. package/dist/executions/executions.controller.js.map +1 -1
  68. package/dist/instance-settings-loader/instance-settings-loader.service.d.ts +3 -1
  69. package/dist/instance-settings-loader/instance-settings-loader.service.js +6 -2
  70. package/dist/instance-settings-loader/instance-settings-loader.service.js.map +1 -1
  71. package/dist/instance-settings-loader/loaders/mcp-settings.loader.d.ts +10 -0
  72. package/dist/instance-settings-loader/loaders/mcp-settings.loader.js +42 -0
  73. package/dist/instance-settings-loader/loaders/mcp-settings.loader.js.map +1 -0
  74. package/dist/instance-settings-loader/loaders/sso.instance-settings-loader.js +9 -4
  75. package/dist/instance-settings-loader/loaders/sso.instance-settings-loader.js.map +1 -1
  76. package/dist/mfa/mfa.service.d.ts +2 -2
  77. package/dist/mfa/mfa.service.js +11 -10
  78. package/dist/mfa/mfa.service.js.map +1 -1
  79. package/dist/modules/chat-hub/chat-hub-extractor.js +1 -1
  80. package/dist/modules/chat-hub/chat-hub-extractor.js.map +1 -1
  81. package/dist/modules/chat-hub/chat-hub-workflow.service.d.ts +1 -1
  82. package/dist/modules/chat-hub/chat-hub-workflow.service.js +4 -4
  83. package/dist/modules/chat-hub/chat-hub-workflow.service.js.map +1 -1
  84. package/dist/modules/community-packages/community-node-types.service.js +3 -1
  85. package/dist/modules/community-packages/community-node-types.service.js.map +1 -1
  86. package/dist/modules/dynamic-credentials.ee/credential-resolvers/n8n-credential-resolver.js +2 -2
  87. package/dist/modules/dynamic-credentials.ee/credential-resolvers/n8n-credential-resolver.js.map +1 -1
  88. package/dist/modules/dynamic-credentials.ee/credential-resolvers/oauth-credential-resolver.js +2 -2
  89. package/dist/modules/dynamic-credentials.ee/credential-resolvers/oauth-credential-resolver.js.map +1 -1
  90. package/dist/modules/dynamic-credentials.ee/credential-resolvers/slack-credential-resolver.js +2 -2
  91. package/dist/modules/dynamic-credentials.ee/credential-resolvers/slack-credential-resolver.js.map +1 -1
  92. package/dist/modules/dynamic-credentials.ee/dynamic-credentials.controller.js +2 -2
  93. package/dist/modules/dynamic-credentials.ee/dynamic-credentials.controller.js.map +1 -1
  94. package/dist/modules/dynamic-credentials.ee/services/credential-check-proxy.service.js +1 -1
  95. package/dist/modules/dynamic-credentials.ee/services/credential-check-proxy.service.js.map +1 -1
  96. package/dist/modules/dynamic-credentials.ee/services/credential-resolver-workflow.service.js +1 -1
  97. package/dist/modules/dynamic-credentials.ee/services/credential-resolver-workflow.service.js.map +1 -1
  98. package/dist/modules/dynamic-credentials.ee/services/credential-resolver.service.js +14 -14
  99. package/dist/modules/dynamic-credentials.ee/services/credential-resolver.service.js.map +1 -1
  100. package/dist/modules/dynamic-credentials.ee/services/dynamic-credential-storage.service.js +1 -1
  101. package/dist/modules/dynamic-credentials.ee/services/dynamic-credential-storage.service.js.map +1 -1
  102. package/dist/modules/dynamic-credentials.ee/services/dynamic-credential.service.js +4 -4
  103. package/dist/modules/dynamic-credentials.ee/services/dynamic-credential.service.js.map +1 -1
  104. package/dist/modules/encryption-key-manager/encryption-bootstrap.service.d.ts +6 -1
  105. package/dist/modules/encryption-key-manager/encryption-bootstrap.service.js +14 -2
  106. package/dist/modules/encryption-key-manager/encryption-bootstrap.service.js.map +1 -1
  107. package/dist/modules/encryption-key-manager/encryption-key.controller.js +1 -0
  108. package/dist/modules/encryption-key-manager/encryption-key.controller.js.map +1 -1
  109. package/dist/modules/encryption-key-manager/key-manager.service.d.ts +2 -1
  110. package/dist/modules/encryption-key-manager/key-manager.service.js +24 -5
  111. package/dist/modules/encryption-key-manager/key-manager.service.js.map +1 -1
  112. package/dist/modules/external-secrets.ee/constants.d.ts +1 -0
  113. package/dist/modules/external-secrets.ee/constants.js +2 -1
  114. package/dist/modules/external-secrets.ee/constants.js.map +1 -1
  115. package/dist/modules/external-secrets.ee/external-secrets-manager.ee.js +4 -4
  116. package/dist/modules/external-secrets.ee/external-secrets-manager.ee.js.map +1 -1
  117. package/dist/modules/external-secrets.ee/secrets-cache.service.d.ts +1 -0
  118. package/dist/modules/external-secrets.ee/secrets-cache.service.js +18 -1
  119. package/dist/modules/external-secrets.ee/secrets-cache.service.js.map +1 -1
  120. package/dist/modules/external-secrets.ee/secrets-providers-connections.controller.ee.js +3 -3
  121. package/dist/modules/external-secrets.ee/secrets-providers-connections.controller.ee.js.map +1 -1
  122. package/dist/modules/external-secrets.ee/secrets-providers-connections.service.ee.d.ts +1 -1
  123. package/dist/modules/external-secrets.ee/secrets-providers-connections.service.ee.js +15 -13
  124. package/dist/modules/external-secrets.ee/secrets-providers-connections.service.ee.js.map +1 -1
  125. package/dist/modules/external-secrets.ee/secrets-providers-project.controller.ee.js +3 -3
  126. package/dist/modules/external-secrets.ee/secrets-providers-project.controller.ee.js.map +1 -1
  127. package/dist/modules/external-secrets.ee/settings-store.service.js +6 -6
  128. package/dist/modules/external-secrets.ee/settings-store.service.js.map +1 -1
  129. package/dist/modules/insights/insights-collection.service.js +7 -1
  130. package/dist/modules/insights/insights-collection.service.js.map +1 -1
  131. package/dist/modules/insights/insights-pruning.service.d.ts +2 -4
  132. package/dist/modules/insights/insights-pruning.service.js +13 -10
  133. package/dist/modules/insights/insights-pruning.service.js.map +1 -1
  134. package/dist/modules/insights/insights.config.js +2 -1
  135. package/dist/modules/insights/insights.config.js.map +1 -1
  136. package/dist/modules/insights/insights.constants.d.ts +2 -0
  137. package/dist/modules/insights/insights.constants.js +3 -1
  138. package/dist/modules/insights/insights.constants.js.map +1 -1
  139. package/dist/modules/insights/insights.service.js +1 -3
  140. package/dist/modules/insights/insights.service.js.map +1 -1
  141. package/dist/modules/instance-ai/compaction.service.d.ts +7 -2
  142. package/dist/modules/instance-ai/compaction.service.js +17 -17
  143. package/dist/modules/instance-ai/compaction.service.js.map +1 -1
  144. package/dist/modules/instance-ai/instance-ai-settings.service.js +4 -4
  145. package/dist/modules/instance-ai/instance-ai-settings.service.js.map +1 -1
  146. package/dist/modules/instance-ai/instance-ai.adapter.service.d.ts +38 -1
  147. package/dist/modules/instance-ai/instance-ai.adapter.service.js +179 -60
  148. package/dist/modules/instance-ai/instance-ai.adapter.service.js.map +1 -1
  149. package/dist/modules/instance-ai/instance-ai.controller.d.ts +2 -2
  150. package/dist/modules/instance-ai/instance-ai.controller.js +7 -17
  151. package/dist/modules/instance-ai/instance-ai.controller.js.map +1 -1
  152. package/dist/modules/instance-ai/instance-ai.service.d.ts +15 -4
  153. package/dist/modules/instance-ai/instance-ai.service.js +489 -76
  154. package/dist/modules/instance-ai/instance-ai.service.js.map +1 -1
  155. package/dist/modules/instance-ai/storage/typeorm-memory-storage.js +11 -1
  156. package/dist/modules/instance-ai/storage/typeorm-memory-storage.js.map +1 -1
  157. package/dist/modules/instance-ai/web-research/fetch-and-extract.d.ts +3 -1
  158. package/dist/modules/instance-ai/web-research/fetch-and-extract.js +13 -11
  159. package/dist/modules/instance-ai/web-research/fetch-and-extract.js.map +1 -1
  160. package/dist/modules/instance-ai/web-research/index.d.ts +0 -1
  161. package/dist/modules/instance-ai/web-research/index.js +1 -3
  162. package/dist/modules/instance-ai/web-research/index.js.map +1 -1
  163. package/dist/modules/instance-registry/checks/check.service.d.ts +43 -0
  164. package/dist/modules/instance-registry/checks/check.service.js +248 -0
  165. package/dist/modules/instance-registry/checks/check.service.js.map +1 -0
  166. package/dist/modules/instance-registry/checks/hostid-clash.check.d.ts +8 -0
  167. package/dist/modules/instance-registry/checks/hostid-clash.check.js +68 -0
  168. package/dist/modules/instance-registry/checks/hostid-clash.check.js.map +1 -0
  169. package/dist/modules/instance-registry/checks/index.d.ts +4 -0
  170. package/dist/modules/instance-registry/checks/index.js +7 -0
  171. package/dist/modules/instance-registry/checks/index.js.map +1 -0
  172. package/dist/modules/instance-registry/checks/lifecycle.check.d.ts +8 -0
  173. package/dist/modules/instance-registry/checks/lifecycle.check.js +52 -0
  174. package/dist/modules/instance-registry/checks/lifecycle.check.js.map +1 -0
  175. package/dist/modules/instance-registry/checks/split-brain.check.d.ts +8 -0
  176. package/dist/modules/instance-registry/checks/split-brain.check.js +67 -0
  177. package/dist/modules/instance-registry/checks/split-brain.check.js.map +1 -0
  178. package/dist/modules/instance-registry/checks/version-mismatch.check.d.ts +8 -0
  179. package/dist/modules/instance-registry/checks/version-mismatch.check.js +55 -0
  180. package/dist/modules/instance-registry/checks/version-mismatch.check.js.map +1 -0
  181. package/dist/modules/instance-registry/instance-registry.controller.d.ts +3 -1
  182. package/dist/modules/instance-registry/instance-registry.controller.js +41 -5
  183. package/dist/modules/instance-registry/instance-registry.controller.js.map +1 -1
  184. package/dist/modules/instance-registry/instance-registry.module.js +3 -9
  185. package/dist/modules/instance-registry/instance-registry.module.js.map +1 -1
  186. package/dist/modules/ldap.ee/helpers.ee.js +1 -1
  187. package/dist/modules/ldap.ee/helpers.ee.js.map +1 -1
  188. package/dist/modules/ldap.ee/ldap.service.ee.js +2 -2
  189. package/dist/modules/ldap.ee/ldap.service.ee.js.map +1 -1
  190. package/dist/modules/mcp/dto/update-workflows-availability.dto.d.ts +15 -0
  191. package/dist/modules/mcp/dto/update-workflows-availability.dto.js +14 -0
  192. package/dist/modules/mcp/dto/update-workflows-availability.dto.js.map +1 -0
  193. package/dist/modules/mcp/mcp-oauth-service.d.ts +6 -0
  194. package/dist/modules/mcp/mcp-oauth-service.js +15 -3
  195. package/dist/modules/mcp/mcp-oauth-service.js.map +1 -1
  196. package/dist/modules/mcp/mcp-oauth-token.service.d.ts +1 -0
  197. package/dist/modules/mcp/mcp-oauth-token.service.js +3 -0
  198. package/dist/modules/mcp/mcp-oauth-token.service.js.map +1 -1
  199. package/dist/modules/mcp/mcp.controller.d.ts +2 -0
  200. package/dist/modules/mcp/mcp.controller.js +49 -11
  201. package/dist/modules/mcp/mcp.controller.js.map +1 -1
  202. package/dist/modules/mcp/mcp.errors.d.ts +6 -0
  203. package/dist/modules/mcp/mcp.errors.js +12 -1
  204. package/dist/modules/mcp/mcp.errors.js.map +1 -1
  205. package/dist/modules/mcp/mcp.module.d.ts +1 -0
  206. package/dist/modules/mcp/mcp.module.js +3 -1
  207. package/dist/modules/mcp/mcp.module.js.map +1 -1
  208. package/dist/modules/mcp/mcp.oauth-clients.controller.d.ts +2 -1
  209. package/dist/modules/mcp/mcp.oauth-clients.controller.js +10 -0
  210. package/dist/modules/mcp/mcp.oauth-clients.controller.js.map +1 -1
  211. package/dist/modules/mcp/mcp.oauth.controller.js +20 -1
  212. package/dist/modules/mcp/mcp.oauth.controller.js.map +1 -1
  213. package/dist/modules/mcp/mcp.service.js +3 -0
  214. package/dist/modules/mcp/mcp.service.js.map +1 -1
  215. package/dist/modules/mcp/mcp.settings.controller.d.ts +11 -12
  216. package/dist/modules/mcp/mcp.settings.controller.js +19 -50
  217. package/dist/modules/mcp/mcp.settings.controller.js.map +1 -1
  218. package/dist/modules/mcp/mcp.settings.service.d.ts +30 -2
  219. package/dist/modules/mcp/mcp.settings.service.js +165 -2
  220. package/dist/modules/mcp/mcp.settings.service.js.map +1 -1
  221. package/dist/modules/mcp/tools/search-executions.tool.d.ts +16 -0
  222. package/dist/modules/mcp/tools/search-executions.tool.js +140 -0
  223. package/dist/modules/mcp/tools/search-executions.tool.js.map +1 -0
  224. package/dist/modules/mcp/tools/workflow-builder/get-workflow-node-types.tool.d.ts +2 -2
  225. package/dist/modules/oauth-jwe/oauth-jwe-decrypt.service.d.ts +7 -0
  226. package/dist/modules/oauth-jwe/oauth-jwe-decrypt.service.js +48 -0
  227. package/dist/modules/oauth-jwe/oauth-jwe-decrypt.service.js.map +1 -0
  228. package/dist/modules/oauth-jwe/oauth-jwe-key.service.d.ts +31 -0
  229. package/dist/modules/oauth-jwe/oauth-jwe-key.service.js +174 -0
  230. package/dist/modules/oauth-jwe/oauth-jwe-key.service.js.map +1 -0
  231. package/dist/modules/oauth-jwe/oauth-jwe.config.d.ts +3 -0
  232. package/dist/modules/oauth-jwe/oauth-jwe.config.js +27 -0
  233. package/dist/modules/oauth-jwe/oauth-jwe.config.js.map +1 -0
  234. package/dist/modules/oauth-jwe/oauth-jwe.constants.d.ts +9 -0
  235. package/dist/modules/oauth-jwe/oauth-jwe.constants.js +15 -0
  236. package/dist/modules/oauth-jwe/oauth-jwe.constants.js.map +1 -0
  237. package/dist/modules/oauth-jwe/oauth-jwe.controller.d.ts +10 -0
  238. package/dist/modules/oauth-jwe/oauth-jwe.controller.js +60 -0
  239. package/dist/modules/oauth-jwe/oauth-jwe.controller.js.map +1 -0
  240. package/dist/modules/oauth-jwe/oauth-jwe.module.d.ts +8 -0
  241. package/dist/modules/oauth-jwe/oauth-jwe.module.js +70 -0
  242. package/dist/modules/oauth-jwe/oauth-jwe.module.js.map +1 -0
  243. package/dist/modules/oauth-jwe/oauth-jwe.schemas.d.ts +131 -0
  244. package/dist/modules/oauth-jwe/oauth-jwe.schemas.js +34 -0
  245. package/dist/modules/oauth-jwe/oauth-jwe.schemas.js.map +1 -0
  246. package/dist/modules/oauth-jwe/oauth-jwe.utils.d.ts +4 -0
  247. package/dist/modules/oauth-jwe/oauth-jwe.utils.js +27 -0
  248. package/dist/modules/oauth-jwe/oauth-jwe.utils.js.map +1 -0
  249. package/dist/modules/source-control.ee/source-control-export.service.ee.js +1 -1
  250. package/dist/modules/source-control.ee/source-control-export.service.ee.js.map +1 -1
  251. package/dist/modules/source-control.ee/source-control-import.service.ee.js +6 -6
  252. package/dist/modules/source-control.ee/source-control-import.service.ee.js.map +1 -1
  253. package/dist/modules/source-control.ee/source-control-preferences.service.ee.js +6 -6
  254. package/dist/modules/source-control.ee/source-control-preferences.service.ee.js.map +1 -1
  255. package/dist/modules/sso-oidc/oidc.service.ee.js +2 -2
  256. package/dist/modules/sso-oidc/oidc.service.ee.js.map +1 -1
  257. package/dist/modules/sso-saml/saml.service.ee.js +6 -6
  258. package/dist/modules/sso-saml/saml.service.ee.js.map +1 -1
  259. package/dist/oauth/oauth-jwe-service.proxy.d.ts +9 -0
  260. package/dist/oauth/oauth-jwe-service.proxy.js +27 -0
  261. package/dist/oauth/oauth-jwe-service.proxy.js.map +1 -0
  262. package/dist/oauth/oauth.service.d.ts +2 -2
  263. package/dist/oauth/oauth.service.js +13 -12
  264. package/dist/oauth/oauth.service.js.map +1 -1
  265. package/dist/posthog/index.d.ts +2 -0
  266. package/dist/posthog/index.js +16 -0
  267. package/dist/posthog/index.js.map +1 -1
  268. package/dist/public-api/v1/handlers/credentials/credentials.service.js +2 -2
  269. package/dist/public-api/v1/handlers/credentials/credentials.service.js.map +1 -1
  270. package/dist/services/dynamic-node-parameters.service.d.ts +1 -0
  271. package/dist/services/dynamic-node-parameters.service.js +29 -12
  272. package/dist/services/dynamic-node-parameters.service.js.map +1 -1
  273. package/dist/services/export.service.js +2 -2
  274. package/dist/services/export.service.js.map +1 -1
  275. package/dist/services/frontend.service.js +18 -0
  276. package/dist/services/frontend.service.js.map +1 -1
  277. package/dist/services/import.service.d.ts +5 -1
  278. package/dist/services/import.service.js +62 -5
  279. package/dist/services/import.service.js.map +1 -1
  280. package/dist/services/redis-client.service.d.ts +6 -5
  281. package/dist/services/redis-client.service.js +19 -12
  282. package/dist/services/redis-client.service.js.map +1 -1
  283. package/dist/services/user.service.js +0 -9
  284. package/dist/services/user.service.js.map +1 -1
  285. package/dist/task-runners/task-broker/auth/task-broker-auth.service.d.ts +4 -4
  286. package/dist/task-runners/task-broker/auth/task-broker-auth.service.js +9 -8
  287. package/dist/task-runners/task-broker/auth/task-broker-auth.service.js.map +1 -1
  288. package/dist/task-runners/task-broker/task-broker-server.js +1 -1
  289. package/dist/task-runners/task-broker/task-broker-server.js.map +1 -1
  290. package/dist/webhooks/test-webhooks.js +16 -2
  291. package/dist/webhooks/test-webhooks.js.map +1 -1
  292. package/dist/workflow-execute-additional-data.js +4 -2
  293. package/dist/workflow-execute-additional-data.js.map +1 -1
  294. package/dist/workflows/workflow-finder.service.d.ts +2 -0
  295. package/dist/workflows/workflow-finder.service.js +12 -1
  296. package/dist/workflows/workflow-finder.service.js.map +1 -1
  297. package/dist/workflows/workflows.controller.d.ts +7 -2
  298. package/dist/workflows/workflows.controller.js +43 -10
  299. package/dist/workflows/workflows.controller.js.map +1 -1
  300. package/package.json +30 -28
  301. package/dist/modules/instance-ai/web-research/ssrf-guard.d.ts +0 -1
  302. package/dist/modules/instance-ai/web-research/ssrf-guard.js +0 -85
  303. package/dist/modules/instance-ai/web-research/ssrf-guard.js.map +0 -1
  304. package/dist/modules/mcp/dto/update-workflow-availability.dto.d.ts +0 -9
  305. package/dist/modules/mcp/dto/update-workflow-availability.dto.js +0 -11
  306. package/dist/modules/mcp/dto/update-workflow-availability.dto.js.map +0 -1
@@ -46,6 +46,7 @@ exports.InstanceAiService = void 0;
46
46
  const api_types_1 = require("@n8n/api-types");
47
47
  const backend_common_1 = require("@n8n/backend-common");
48
48
  const config_1 = require("@n8n/config");
49
+ const n8n_core_1 = require("n8n-core");
49
50
  const constants_1 = require("@n8n/constants");
50
51
  const db_1 = require("@n8n/db");
51
52
  const di_1 = require("@n8n/di");
@@ -80,6 +81,58 @@ function createInertAbortSignal() {
80
81
  const ORCHESTRATOR_AGENT_ID = 'agent-001';
81
82
  const INSTANCE_AI_FEEDBACK_NAMESPACE = 'c5be4c87-5b6e-49ed-afe1-9c5c1f99a5c0';
82
83
  const MAX_CONCURRENT_BACKGROUND_TASKS_PER_THREAD = 5;
84
+ function estimateTokens(text) {
85
+ return Math.ceil(text.length / 4);
86
+ }
87
+ function stringifyForContextValue(value) {
88
+ if (typeof value === 'string')
89
+ return value;
90
+ try {
91
+ return JSON.stringify(value);
92
+ }
93
+ catch {
94
+ return String(value);
95
+ }
96
+ }
97
+ const PLANNED_TASK_CONTEXT_VALUE_LIMIT = 1_500;
98
+ function truncateContextValue(value) {
99
+ if (value.length <= PLANNED_TASK_CONTEXT_VALUE_LIMIT)
100
+ return value;
101
+ return `${value.slice(0, PLANNED_TASK_CONTEXT_VALUE_LIMIT)}...`;
102
+ }
103
+ function buildPlannedTaskConversationContext(task, graph) {
104
+ if (!graph)
105
+ return undefined;
106
+ const parts = [
107
+ `Approved plan task: ${task.title}`,
108
+ `Task id: ${task.id}`,
109
+ `Task kind: ${task.kind}`,
110
+ `Plan run id: ${graph.planRunId}`,
111
+ ];
112
+ if (task.workflowId) {
113
+ parts.push(`Target workflow id: ${task.workflowId}`);
114
+ }
115
+ const dependencies = graph.tasks.filter((candidate) => task.deps.includes(candidate.id));
116
+ if (dependencies.length > 0) {
117
+ parts.push('Completed dependency context:');
118
+ for (const dependency of dependencies) {
119
+ const dependencyParts = [
120
+ `- ${dependency.id} (${dependency.kind}, ${dependency.status}): ${dependency.title}`,
121
+ ];
122
+ if (dependency.result) {
123
+ dependencyParts.push(`result=${truncateContextValue(dependency.result)}`);
124
+ }
125
+ if (dependency.error) {
126
+ dependencyParts.push(`error=${truncateContextValue(dependency.error)}`);
127
+ }
128
+ if (dependency.outcome) {
129
+ dependencyParts.push(`outcome=${truncateContextValue(stringifyForContextValue(dependency.outcome))}`);
130
+ }
131
+ parts.push(dependencyParts.join(' '));
132
+ }
133
+ }
134
+ return parts.join('\n');
135
+ }
83
136
  function getProxyFetch() {
84
137
  const proxyUrl = process.env.HTTPS_PROXY || process.env.HTTP_PROXY;
85
138
  if (!proxyUrl)
@@ -91,8 +144,39 @@ function getProxyFetch() {
91
144
  dispatcher,
92
145
  }));
93
146
  }
147
+ function toConfirmationData(request) {
148
+ switch (request.kind) {
149
+ case 'approval':
150
+ return { approved: request.approved, userInput: request.userInput };
151
+ case 'domainAccessApprove':
152
+ return { approved: true, domainAccessAction: request.domainAccessAction };
153
+ case 'domainAccessDeny':
154
+ return { approved: false };
155
+ case 'questions':
156
+ return { approved: true, answers: request.answers };
157
+ case 'credentialSelection':
158
+ return { approved: true, credentials: request.credentials };
159
+ case 'resourceDecision':
160
+ return { approved: true, resourceDecision: request.resourceDecision };
161
+ case 'setupWorkflowApply':
162
+ return {
163
+ approved: true,
164
+ action: 'apply',
165
+ nodeCredentials: request.nodeCredentials,
166
+ nodeParameters: request.nodeParameters,
167
+ };
168
+ case 'setupWorkflowTestTrigger':
169
+ return {
170
+ approved: true,
171
+ action: 'test-trigger',
172
+ testTriggerNode: request.testTriggerNode,
173
+ nodeCredentials: request.nodeCredentials,
174
+ nodeParameters: request.nodeParameters,
175
+ };
176
+ }
177
+ }
94
178
  let InstanceAiService = class InstanceAiService {
95
- constructor(logger, globalConfig, adapterService, eventBus, settingsService, compositeStore, compactionService, aiService, push, threadRepo, urlService, dbSnapshotStorage, dbIterationLogStorage, sourceControlPreferencesService, telemetry, userRepository, aiBuilderTemporaryWorkflowRepository) {
179
+ constructor(logger, globalConfig, adapterService, eventBus, settingsService, compositeStore, compactionService, aiService, push, threadRepo, urlService, dbSnapshotStorage, dbIterationLogStorage, sourceControlPreferencesService, telemetry, userRepository, aiBuilderTemporaryWorkflowRepository, errorReporter) {
96
180
  this.adapterService = adapterService;
97
181
  this.eventBus = eventBus;
98
182
  this.settingsService = settingsService;
@@ -108,6 +192,7 @@ let InstanceAiService = class InstanceAiService {
108
192
  this.telemetry = telemetry;
109
193
  this.userRepository = userRepository;
110
194
  this.aiBuilderTemporaryWorkflowRepository = aiBuilderTemporaryWorkflowRepository;
195
+ this.errorReporter = errorReporter;
111
196
  this.mcpClientManager = new instance_ai_1.McpClientManager();
112
197
  this.runState = new instance_ai_1.RunStateRegistry();
113
198
  this.backgroundTasks = new instance_ai_1.BackgroundTaskManager(MAX_CONCURRENT_BACKGROUND_TASKS_PER_THREAD);
@@ -117,10 +202,12 @@ let InstanceAiService = class InstanceAiService {
117
202
  this.domainAccessTrackersByThread = new Map();
118
203
  this.threadPushRef = new Map();
119
204
  this.schedulerLocks = new Map();
205
+ this.pendingCheckpointReentries = new Map();
120
206
  this.creditedThreads = new Set();
121
207
  this.traceReplay = new trace_replay_state_1.TraceReplayState();
122
208
  this.logger = logger.scoped('instance-ai');
123
209
  this.instanceAiConfig = globalConfig.instanceAi;
210
+ this.builderSandboxSessions = new instance_ai_1.BuilderSandboxSessionRegistry(this.instanceAiConfig.builderSandboxTtlMs);
124
211
  this.defaultTimeZone = globalConfig.generic.timezone;
125
212
  const editorBaseUrl = globalConfig.editorBaseUrl || `http://localhost:${globalConfig.port}`;
126
213
  const restEndpoint = globalConfig.endpoints.rest;
@@ -166,6 +253,7 @@ let InstanceAiService = class InstanceAiService {
166
253
  daytonaApiUrl: daytonaApiUrl || undefined,
167
254
  daytonaApiKey: daytonaApiKey || undefined,
168
255
  image: sandboxImage || undefined,
256
+ n8nVersion: constants_2.N8N_VERSION || undefined,
169
257
  timeout: sandboxTimeout,
170
258
  };
171
259
  }
@@ -224,7 +312,7 @@ let InstanceAiService = class InstanceAiService {
224
312
  if (!config.enabled)
225
313
  return undefined;
226
314
  if (config.provider === 'daytona') {
227
- return new instance_ai_1.BuilderSandboxFactory(config, new instance_ai_1.SnapshotManager(config.image, this.logger), this.logger);
315
+ return new instance_ai_1.BuilderSandboxFactory(config, new instance_ai_1.SnapshotManager(config.image, this.logger, config.n8nVersion, this.errorReporter), this.logger, this.errorReporter);
228
316
  }
229
317
  return new instance_ai_1.BuilderSandboxFactory(config, undefined, this.logger);
230
318
  }
@@ -599,6 +687,9 @@ let InstanceAiService = class InstanceAiService {
599
687
  user,
600
688
  researchMode,
601
689
  });
690
+ if (timeZone) {
691
+ this.runState.setTimeZone(threadId, timeZone);
692
+ }
602
693
  if (pushRef !== undefined) {
603
694
  this.threadPushRef.set(threadId, pushRef);
604
695
  }
@@ -633,6 +724,7 @@ let InstanceAiService = class InstanceAiService {
633
724
  void this.handlePlannedTaskSettlement(user, task, 'cancelled');
634
725
  }
635
726
  }
727
+ void this.cancelAwaitingApprovalPlan(threadId);
636
728
  const { active, suspended } = this.runState.cancelThread(threadId);
637
729
  if (active) {
638
730
  active.abortController.abort();
@@ -763,6 +855,7 @@ let InstanceAiService = class InstanceAiService {
763
855
  this.domainAccessTrackersByThread.delete(threadId);
764
856
  this.threadPushRef.delete(threadId);
765
857
  this.deleteTraceContextsForThread(threadId);
858
+ await this.builderSandboxSessions.cleanupThread(threadId, 'thread_cleared');
766
859
  await this.destroySandbox(threadId);
767
860
  await this.reapAiTemporaryForThreadCleanup(threadId);
768
861
  this.eventBus.clearThread(threadId);
@@ -801,7 +894,10 @@ let InstanceAiService = class InstanceAiService {
801
894
  }
802
895
  this.gatewayRegistry.disconnectAll();
803
896
  const sandboxCleanups = [...this.sandboxes.keys()].map(async (threadId) => await this.destroySandbox(threadId));
804
- await Promise.allSettled(sandboxCleanups);
897
+ await Promise.allSettled([
898
+ ...sandboxCleanups,
899
+ this.builderSandboxSessions.cleanupAll('service_shutdown'),
900
+ ]);
805
901
  this.domainAccessTrackersByThread.clear();
806
902
  this.traceContextsByRunId.clear();
807
903
  this.eventBus.clear();
@@ -846,7 +942,7 @@ let InstanceAiService = class InstanceAiService {
846
942
  })),
847
943
  };
848
944
  }
849
- buildPlannedTaskFollowUpMessage(type, graph, failedTask) {
945
+ buildPlannedTaskFollowUpMessage(type, graph, options = {}) {
850
946
  const payload = {
851
947
  tasks: graph.tasks.map((task) => ({
852
948
  id: task.id,
@@ -858,13 +954,31 @@ let InstanceAiService = class InstanceAiService {
858
954
  outcome: task.outcome,
859
955
  })),
860
956
  };
861
- if (failedTask) {
957
+ if (options.failedTask) {
862
958
  payload.failedTask = {
863
- id: failedTask.id,
864
- title: failedTask.title,
865
- kind: failedTask.kind,
866
- error: failedTask.error,
867
- result: failedTask.result,
959
+ id: options.failedTask.id,
960
+ title: options.failedTask.title,
961
+ kind: options.failedTask.kind,
962
+ error: options.failedTask.error,
963
+ result: options.failedTask.result,
964
+ };
965
+ }
966
+ if (options.checkpoint) {
967
+ const depOutcomes = graph.tasks
968
+ .filter((t) => options.checkpoint.deps.includes(t.id))
969
+ .map((t) => ({
970
+ id: t.id,
971
+ title: t.title,
972
+ kind: t.kind,
973
+ status: t.status,
974
+ result: t.result,
975
+ outcome: t.outcome,
976
+ }));
977
+ payload.checkpoint = {
978
+ id: options.checkpoint.id,
979
+ title: options.checkpoint.title,
980
+ instructions: options.checkpoint.spec,
981
+ dependsOn: depOutcomes,
868
982
  };
869
983
  }
870
984
  return `<planned-task-follow-up type="${type}">\n${JSON.stringify(payload, null, 2)}\n</planned-task-follow-up>\n\n${internal_messages_1.AUTO_FOLLOW_UP_MESSAGE}`;
@@ -887,6 +1001,28 @@ let InstanceAiService = class InstanceAiService {
887
1001
  payload: { tasks },
888
1002
  });
889
1003
  }
1004
+ async cancelAwaitingApprovalPlan(threadId) {
1005
+ try {
1006
+ const { plannedTaskService, taskStorage } = await this.createPlannedTaskState();
1007
+ const graph = await plannedTaskService.getGraph(threadId);
1008
+ if (!graph || graph.status !== 'awaiting_approval')
1009
+ return;
1010
+ await plannedTaskService.clear(threadId);
1011
+ await taskStorage.save(threadId, { tasks: [] });
1012
+ this.eventBus.publish(threadId, {
1013
+ type: 'tasks-update',
1014
+ runId: graph.planRunId,
1015
+ agentId: ORCHESTRATOR_AGENT_ID,
1016
+ payload: { tasks: { tasks: [] }, planItems: [] },
1017
+ });
1018
+ }
1019
+ catch (error) {
1020
+ this.logger.warn('Failed to clean up awaiting_approval plan on cancel', {
1021
+ threadId,
1022
+ error: error instanceof Error ? error.message : String(error),
1023
+ });
1024
+ }
1025
+ }
890
1026
  async createExecutionEnvironment(user, threadId, runId, abortSignal, researchMode, messageGroupId, pushRef) {
891
1027
  const localGatewayDisabled = await this.settingsService.isLocalGatewayDisabledForUser(user.id);
892
1028
  const userGateway = this.gatewayRegistry.findGateway(user.id);
@@ -981,6 +1117,9 @@ let InstanceAiService = class InstanceAiService {
981
1117
  subAgentMaxSteps: this.instanceAiConfig.subAgentMaxSteps,
982
1118
  eventBus: this.eventBus,
983
1119
  logger: this.logger,
1120
+ trackTelemetry: (eventName, properties) => {
1121
+ this.telemetry.track(eventName, properties);
1122
+ },
984
1123
  domainTools,
985
1124
  abortSignal,
986
1125
  taskStorage,
@@ -1014,6 +1153,7 @@ let InstanceAiService = class InstanceAiService {
1014
1153
  workflowTaskService: workflowTasks,
1015
1154
  workspace: sandboxEntry?.workspace,
1016
1155
  builderSandboxFactory: await this.createBuilderFactory(user),
1156
+ builderSandboxSessionRegistry: this.builderSandboxSessions,
1017
1157
  nodeDefinitionDirs: nodeDefDirs.length > 0 ? nodeDefDirs : undefined,
1018
1158
  domainContext: context,
1019
1159
  tracingProxyConfig,
@@ -1032,8 +1172,9 @@ let InstanceAiService = class InstanceAiService {
1032
1172
  sandboxEntry,
1033
1173
  };
1034
1174
  }
1035
- async dispatchPlannedTask(task, context) {
1175
+ async dispatchPlannedTask(task, context, graph) {
1036
1176
  const taskContext = this.createPlannedTaskContext(task.kind, context);
1177
+ const conversationContext = buildPlannedTaskConversationContext(task, graph);
1037
1178
  let started = null;
1038
1179
  switch (task.kind) {
1039
1180
  case 'build-workflow':
@@ -1041,12 +1182,14 @@ let InstanceAiService = class InstanceAiService {
1041
1182
  task: task.spec,
1042
1183
  workflowId: task.workflowId,
1043
1184
  plannedTaskId: task.id,
1185
+ conversationContext,
1044
1186
  });
1045
1187
  break;
1046
1188
  case 'manage-data-tables':
1047
1189
  started = await (0, instance_ai_1.startDataTableAgentTask)(taskContext, {
1048
1190
  task: task.spec,
1049
1191
  plannedTaskId: task.id,
1192
+ conversationContext,
1050
1193
  });
1051
1194
  break;
1052
1195
  case 'research':
@@ -1054,6 +1197,7 @@ let InstanceAiService = class InstanceAiService {
1054
1197
  goal: task.title,
1055
1198
  constraints: task.spec,
1056
1199
  plannedTaskId: task.id,
1200
+ conversationContext,
1057
1201
  });
1058
1202
  break;
1059
1203
  case 'delegate':
@@ -1062,6 +1206,7 @@ let InstanceAiService = class InstanceAiService {
1062
1206
  spec: task.spec,
1063
1207
  tools: task.tools ?? [],
1064
1208
  plannedTaskId: task.id,
1209
+ conversationContext,
1065
1210
  });
1066
1211
  break;
1067
1212
  }
@@ -1092,6 +1237,34 @@ let InstanceAiService = class InstanceAiService {
1092
1237
  domainTools: (0, instance_ai_1.createAllTools)(taskDomainContext),
1093
1238
  };
1094
1239
  }
1240
+ async getCheckpointAllowedWorkflowIds(threadId, checkpointTaskId) {
1241
+ try {
1242
+ const { plannedTaskService } = await this.createPlannedTaskState();
1243
+ const graph = await plannedTaskService.getGraph(threadId);
1244
+ const checkpoint = graph?.tasks.find((t) => t.id === checkpointTaskId);
1245
+ if (!graph || !checkpoint)
1246
+ return new Set();
1247
+ const deps = new Set(checkpoint.deps);
1248
+ const allowed = new Set();
1249
+ for (const task of graph.tasks) {
1250
+ if (!deps.has(task.id))
1251
+ continue;
1252
+ const workflowId = task.outcome?.workflowId;
1253
+ if (typeof workflowId === 'string' && workflowId.length > 0) {
1254
+ allowed.add(workflowId);
1255
+ }
1256
+ }
1257
+ return allowed;
1258
+ }
1259
+ catch (error) {
1260
+ this.logger.warn('Failed to resolve checkpoint allowed workflow IDs', {
1261
+ threadId,
1262
+ checkpointTaskId,
1263
+ error: error instanceof Error ? error.message : String(error),
1264
+ });
1265
+ return new Set();
1266
+ }
1267
+ }
1095
1268
  async handlePlannedTaskSettlement(user, task, status) {
1096
1269
  if (!task.plannedTaskId)
1097
1270
  return;
@@ -1118,7 +1291,7 @@ let InstanceAiService = class InstanceAiService {
1118
1291
  }
1119
1292
  await this.schedulePlannedTasks(user, task.threadId);
1120
1293
  }
1121
- async startInternalFollowUpRun(user, threadId, message, researchMode, messageGroupId, isReplanFollowUp = false) {
1294
+ async startInternalFollowUpRun(user, threadId, message, researchMode, messageGroupId, isReplanFollowUp = false, checkpoint) {
1122
1295
  if (this.runState.hasLiveRun(threadId)) {
1123
1296
  this.logger.warn('Skipping internal follow-up: active run exists', { threadId });
1124
1297
  return '';
@@ -1129,7 +1302,8 @@ let InstanceAiService = class InstanceAiService {
1129
1302
  researchMode,
1130
1303
  messageGroupId,
1131
1304
  });
1132
- void this.executeRun(user, threadId, runId, message, abortController, researchMode, undefined, messageGroupId, undefined, isReplanFollowUp);
1305
+ const timeZone = this.runState.getTimeZone(threadId) ?? this.defaultTimeZone;
1306
+ void this.executeRun(user, threadId, runId, message, abortController, researchMode, undefined, messageGroupId, timeZone, isReplanFollowUp, checkpoint);
1133
1307
  return runId;
1134
1308
  }
1135
1309
  async schedulePlannedTasks(user, threadId) {
@@ -1151,22 +1325,50 @@ let InstanceAiService = class InstanceAiService {
1151
1325
  return;
1152
1326
  if (action.type === 'replan') {
1153
1327
  await this.syncPlannedTasksToUi(threadId, action.graph);
1154
- await this.startInternalFollowUpRun(user, threadId, this.buildPlannedTaskFollowUpMessage('replan', action.graph, action.failedTask), this.runState.getThreadResearchMode(threadId), action.graph.messageGroupId, true);
1328
+ const startedRunId = await this.startInternalFollowUpRun(user, threadId, this.buildPlannedTaskFollowUpMessage('replan', action.graph, {
1329
+ failedTask: action.failedTask,
1330
+ }), this.runState.getThreadResearchMode(threadId), action.graph.messageGroupId, true);
1331
+ if (!startedRunId) {
1332
+ await plannedTaskService.revertToActive(threadId);
1333
+ }
1155
1334
  return;
1156
1335
  }
1157
1336
  if (action.type === 'synthesize') {
1158
1337
  await this.syncPlannedTasksToUi(threadId, action.graph);
1159
- await this.startInternalFollowUpRun(user, threadId, this.buildPlannedTaskFollowUpMessage('synthesize', action.graph), this.runState.getThreadResearchMode(threadId), action.graph.messageGroupId);
1338
+ const startedRunId = await this.startInternalFollowUpRun(user, threadId, this.buildPlannedTaskFollowUpMessage('synthesize', action.graph), this.runState.getThreadResearchMode(threadId), action.graph.messageGroupId);
1339
+ if (!startedRunId) {
1340
+ await plannedTaskService.revertToActive(threadId);
1341
+ }
1342
+ return;
1343
+ }
1344
+ if (action.type === 'orchestrate-checkpoint') {
1345
+ if (this.runState.hasLiveRun(threadId)) {
1346
+ return;
1347
+ }
1348
+ const checkpoint = action.tasks[0];
1349
+ await plannedTaskService.markRunning(threadId, checkpoint.id, {
1350
+ agentId: ORCHESTRATOR_AGENT_ID,
1351
+ });
1352
+ const graphAfterMark = (await plannedTaskService.getGraph(threadId)) ?? action.graph;
1353
+ await this.syncPlannedTasksToUi(threadId, graphAfterMark);
1354
+ const checkpointRecord = graphAfterMark.tasks.find((t) => t.id === checkpoint.id) ?? checkpoint;
1355
+ const startedRunId = await this.startInternalFollowUpRun(user, threadId, this.buildPlannedTaskFollowUpMessage('checkpoint', graphAfterMark, {
1356
+ checkpoint: checkpointRecord,
1357
+ }), this.runState.getThreadResearchMode(threadId), action.graph.messageGroupId, false, { isCheckpointFollowUp: true, checkpointTaskId: checkpoint.id });
1358
+ if (!startedRunId) {
1359
+ this.logger.warn('Checkpoint follow-up run did not start — reverting checkpoint to planned for retry', { threadId, checkpointTaskId: checkpoint.id });
1360
+ await plannedTaskService.revertCheckpointToPlanned(threadId, checkpoint.id);
1361
+ }
1160
1362
  return;
1161
1363
  }
1162
1364
  const environment = await this.createExecutionEnvironment(user, threadId, action.graph.planRunId, createInertAbortSignal(), this.runState.getThreadResearchMode(threadId), action.graph.messageGroupId);
1163
1365
  environment.orchestrationContext.tracing = this.getTraceContext(action.graph.planRunId);
1164
1366
  for (const task of action.tasks) {
1165
- await this.dispatchPlannedTask(task, environment.orchestrationContext);
1367
+ await this.dispatchPlannedTask(task, environment.orchestrationContext, action.graph);
1166
1368
  }
1167
1369
  await this.doSchedulePlannedTasks(user, threadId);
1168
1370
  }
1169
- async executeRun(user, threadId, runId, message, abortController, researchMode, attachments, messageGroupId, timeZone, isReplanFollowUp = false) {
1371
+ async executeRun(user, threadId, runId, message, abortController, researchMode, attachments, messageGroupId, timeZone, isReplanFollowUp = false, checkpoint) {
1170
1372
  const signal = abortController.signal;
1171
1373
  let mastraRunId = '';
1172
1374
  let tracing;
@@ -1197,6 +1399,15 @@ let InstanceAiService = class InstanceAiService {
1197
1399
  orchestrationContext.currentUserMessage = message;
1198
1400
  orchestrationContext.isReplanFollowUp = isReplanFollowUp;
1199
1401
  orchestrationContext.timeZone = timeZone ?? this.defaultTimeZone;
1402
+ if (checkpoint?.isCheckpointFollowUp) {
1403
+ orchestrationContext.isCheckpointFollowUp = true;
1404
+ orchestrationContext.checkpointTaskId = checkpoint.checkpointTaskId;
1405
+ context.permissions = {
1406
+ ...context.permissions,
1407
+ ...(instance_ai_1.PLANNED_TASK_PERMISSION_OVERRIDES.checkpoint ?? {}),
1408
+ };
1409
+ context.allowedRunWorkflowIds = await this.getCheckpointAllowedWorkflowIds(threadId, checkpoint.checkpointTaskId);
1410
+ }
1200
1411
  if (attachments && attachments.length > 0) {
1201
1412
  context.currentUserAttachments = attachments;
1202
1413
  }
@@ -1257,10 +1468,25 @@ let InstanceAiService = class InstanceAiService {
1257
1468
  mcpServers,
1258
1469
  memoryConfig,
1259
1470
  memory,
1260
- workspace: orchestrationContext.workspace,
1261
1471
  disableDeferredTools: true,
1262
1472
  timeZone: timeZone ?? this.defaultTimeZone,
1263
1473
  });
1474
+ const enrichedMessage = await this.buildMessageWithRunningTasks(threadId, message);
1475
+ let nonStructuredAttachments = [];
1476
+ let attachmentManifest = '';
1477
+ let hasParseableAttachment = false;
1478
+ if (attachments && attachments.length > 0) {
1479
+ const classifiedAttachments = (0, instance_ai_1.classifyAttachments)(attachments);
1480
+ nonStructuredAttachments = attachments.filter((attachment) => !(0, instance_ai_1.isStructuredAttachment)(attachment));
1481
+ hasParseableAttachment = classifiedAttachments.some((attachment) => attachment.parseable);
1482
+ attachmentManifest = (0, instance_ai_1.buildAttachmentManifest)(classifiedAttachments);
1483
+ }
1484
+ const messageWithoutSummary = !message && hasParseableAttachment
1485
+ ? `The user attached file(s) without a message. Inspect the first parseable attachment with parse-file and provide a concise summary.\n\n${attachmentManifest}`
1486
+ : attachmentManifest
1487
+ ? `${enrichedMessage}\n\n${attachmentManifest}`
1488
+ : enrichedMessage;
1489
+ const messageWithoutSummaryTokens = estimateTokens(messageWithoutSummary);
1264
1490
  this.eventBus.publish(threadId, {
1265
1491
  type: 'status',
1266
1492
  runId,
@@ -1275,17 +1501,22 @@ let InstanceAiService = class InstanceAiService {
1275
1501
  inputs: {
1276
1502
  threadId,
1277
1503
  lastMessages: this.instanceAiConfig.lastMessages ?? 20,
1504
+ currentInputTokens: messageWithoutSummaryTokens,
1278
1505
  },
1279
1506
  })
1280
1507
  : undefined;
1281
1508
  let conversationSummary;
1282
1509
  try {
1283
- conversationSummary = await this.compactionService.prepareCompactedContext(threadId, memory, modelId, this.instanceAiConfig.lastMessages ?? 20);
1510
+ conversationSummary = await this.compactionService.prepareCompactedContext(threadId, memory, modelId, this.instanceAiConfig.lastMessages ?? 20, 0.8, {
1511
+ label: 'orchestrator-current-input',
1512
+ text: messageWithoutSummary,
1513
+ });
1284
1514
  if (contextCompactionRun && tracing) {
1285
1515
  await tracing.finishRun(contextCompactionRun, {
1286
1516
  outputs: {
1287
1517
  summarized: Boolean(conversationSummary),
1288
1518
  summary: conversationSummary ?? '',
1519
+ currentInputTokens: messageWithoutSummaryTokens,
1289
1520
  },
1290
1521
  metadata: { final_status: 'completed' },
1291
1522
  });
@@ -1319,41 +1550,23 @@ let InstanceAiService = class InstanceAiService {
1319
1550
  : undefined;
1320
1551
  let streamInput;
1321
1552
  try {
1322
- const enrichedMessage = await this.buildMessageWithRunningTasks(threadId, message);
1323
- let fullMessage = conversationSummary
1324
- ? `${conversationSummary}\n\n${enrichedMessage}`
1325
- : enrichedMessage;
1326
- if (attachments && attachments.length > 0) {
1327
- const classified = (0, instance_ai_1.classifyAttachments)(attachments);
1328
- const nonStructured = attachments.filter((a) => !(0, instance_ai_1.isStructuredAttachment)(a));
1329
- const hasParseable = classified.some((c) => c.parseable);
1330
- const manifest = (0, instance_ai_1.buildAttachmentManifest)(classified);
1331
- if (!message && hasParseable) {
1332
- fullMessage = conversationSummary
1333
- ? `${conversationSummary}\n\nThe user attached file(s) without a message. Inspect the first parseable attachment with parse-file and provide a concise summary.\n\n${manifest}`
1334
- : `The user attached file(s) without a message. Inspect the first parseable attachment with parse-file and provide a concise summary.\n\n${manifest}`;
1335
- }
1336
- else {
1337
- fullMessage = `${fullMessage}\n\n${manifest}`;
1338
- }
1339
- if (nonStructured.length > 0) {
1340
- streamInput = [
1341
- {
1342
- role: 'user',
1343
- content: [
1344
- { type: 'text', text: fullMessage },
1345
- ...nonStructured.map((a) => ({
1346
- type: 'file',
1347
- data: a.data,
1348
- mimeType: a.mimeType,
1349
- })),
1350
- ],
1351
- },
1352
- ];
1353
- }
1354
- else {
1355
- streamInput = fullMessage;
1356
- }
1553
+ const fullMessage = conversationSummary
1554
+ ? `${conversationSummary}\n\n${messageWithoutSummary}`
1555
+ : messageWithoutSummary;
1556
+ if (nonStructuredAttachments.length > 0) {
1557
+ streamInput = [
1558
+ {
1559
+ role: 'user',
1560
+ content: [
1561
+ { type: 'text', text: fullMessage },
1562
+ ...nonStructuredAttachments.map((attachment) => ({
1563
+ type: 'file',
1564
+ data: attachment.data,
1565
+ mimeType: attachment.mimeType,
1566
+ })),
1567
+ ],
1568
+ },
1569
+ ];
1357
1570
  }
1358
1571
  else {
1359
1572
  streamInput = fullMessage;
@@ -1364,7 +1577,7 @@ let InstanceAiService = class InstanceAiService {
1364
1577
  : {
1365
1578
  fullMessage,
1366
1579
  attachmentCount: attachments?.length ?? 0,
1367
- nonStructuredAttachmentCount: attachments?.filter((a) => !(0, instance_ai_1.isStructuredAttachment)(a)).length ?? 0,
1580
+ nonStructuredAttachmentCount: nonStructuredAttachments.length,
1368
1581
  };
1369
1582
  await tracing.finishRun(promptBuildRun, {
1370
1583
  outputs: traceOutput,
@@ -1434,6 +1647,7 @@ let InstanceAiService = class InstanceAiService {
1434
1647
  messageGroupId,
1435
1648
  createdAt: Date.now(),
1436
1649
  tracing,
1650
+ checkpoint,
1437
1651
  });
1438
1652
  }
1439
1653
  const intermediateText = await (result.text ?? Promise.resolve(''));
@@ -1533,9 +1747,125 @@ let InstanceAiService = class InstanceAiService {
1533
1747
  if (!this.runState.hasSuspendedRun(threadId) && mastraRunId) {
1534
1748
  void this.cleanupMastraSnapshots(mastraRunId);
1535
1749
  }
1750
+ if (!this.runState.hasSuspendedRun(threadId)) {
1751
+ if (checkpoint?.isCheckpointFollowUp) {
1752
+ await this.finalizeCheckpointFollowUp(user, threadId, checkpoint.checkpointTaskId);
1753
+ }
1754
+ else {
1755
+ await this.schedulePlannedTasks(user, threadId);
1756
+ }
1757
+ await this.drainPendingCheckpointReentries(user, threadId);
1758
+ }
1759
+ }
1760
+ }
1761
+ queuePendingCheckpointReentry(threadId, checkpointTaskId) {
1762
+ let set = this.pendingCheckpointReentries.get(threadId);
1763
+ if (!set) {
1764
+ set = new Set();
1765
+ this.pendingCheckpointReentries.set(threadId, set);
1536
1766
  }
1767
+ set.add(checkpointTaskId);
1537
1768
  }
1538
- async resolveConfirmation(requestingUserId, requestId, data) {
1769
+ async drainPendingCheckpointReentries(user, threadId) {
1770
+ const set = this.pendingCheckpointReentries.get(threadId);
1771
+ if (!set || set.size === 0)
1772
+ return;
1773
+ const snapshot = [...set];
1774
+ for (const checkpointTaskId of snapshot) {
1775
+ if (this.runState.getActiveRunId(threadId) || this.runState.hasSuspendedRun(threadId)) {
1776
+ return;
1777
+ }
1778
+ const siblings = this.backgroundTasks.getRunningTasksByParentCheckpoint(threadId, checkpointTaskId);
1779
+ if (siblings.length > 0)
1780
+ continue;
1781
+ set.delete(checkpointTaskId);
1782
+ await this.reenterCheckpointById(user, threadId, checkpointTaskId);
1783
+ }
1784
+ if (set.size === 0)
1785
+ this.pendingCheckpointReentries.delete(threadId);
1786
+ }
1787
+ async reenterCheckpointById(user, threadId, checkpointTaskId, messageGroupId) {
1788
+ try {
1789
+ const { plannedTaskService } = await this.createPlannedTaskState();
1790
+ const graph = await plannedTaskService.getGraph(threadId);
1791
+ const checkpoint = graph?.tasks.find((t) => t.id === checkpointTaskId);
1792
+ if (!graph || !checkpoint || checkpoint.kind !== 'checkpoint')
1793
+ return false;
1794
+ if (checkpoint.status !== 'running')
1795
+ return false;
1796
+ const startedRunId = await this.startInternalFollowUpRun(user, threadId, this.buildPlannedTaskFollowUpMessage('checkpoint', graph, { checkpoint }), this.runState.getThreadResearchMode(threadId), messageGroupId, false, { isCheckpointFollowUp: true, checkpointTaskId });
1797
+ if (!startedRunId)
1798
+ return false;
1799
+ this.logger.debug('Re-entered checkpoint follow-up', {
1800
+ threadId,
1801
+ checkpointTaskId,
1802
+ messageGroupId,
1803
+ });
1804
+ return true;
1805
+ }
1806
+ catch (error) {
1807
+ this.logger.error('Failed to re-enter checkpoint follow-up', {
1808
+ threadId,
1809
+ checkpointTaskId,
1810
+ error: error instanceof Error ? error.message : String(error),
1811
+ });
1812
+ return false;
1813
+ }
1814
+ }
1815
+ async maybeReenterParentCheckpoint(user, threadId, task) {
1816
+ const parentCheckpointId = task.parentCheckpointId;
1817
+ if (!parentCheckpointId)
1818
+ return false;
1819
+ const siblings = this.backgroundTasks
1820
+ .getRunningTasksByParentCheckpoint(threadId, parentCheckpointId)
1821
+ .filter((t) => t.taskId !== task.taskId);
1822
+ if (siblings.length > 0)
1823
+ return false;
1824
+ if (this.runState.getActiveRunId(threadId) || this.runState.hasSuspendedRun(threadId)) {
1825
+ return false;
1826
+ }
1827
+ return await this.reenterCheckpointById(user, threadId, parentCheckpointId, task.messageGroupId);
1828
+ }
1829
+ async finalizeCheckpointFollowUp(user, threadId, checkpointTaskId) {
1830
+ try {
1831
+ const { plannedTaskService } = await this.createPlannedTaskState();
1832
+ const graph = await plannedTaskService.getGraph(threadId);
1833
+ const task = graph?.tasks.find((t) => t.id === checkpointTaskId);
1834
+ if (task && task.status === 'running') {
1835
+ const inflightChildren = this.backgroundTasks.getRunningTasksByParentCheckpoint(threadId, checkpointTaskId);
1836
+ if (inflightChildren.length > 0) {
1837
+ this.logger.debug('Checkpoint run ended with in-flight child tasks — deferring finalization', {
1838
+ threadId,
1839
+ checkpointTaskId,
1840
+ inflightTaskIds: inflightChildren.map((t) => t.taskId),
1841
+ });
1842
+ }
1843
+ else {
1844
+ this.logger.warn('Checkpoint run ended without reporting completion — marking failed', {
1845
+ threadId,
1846
+ checkpointTaskId,
1847
+ });
1848
+ await plannedTaskService.markCheckpointFailed(threadId, checkpointTaskId, {
1849
+ error: 'Checkpoint run ended without reporting completion',
1850
+ });
1851
+ const nextGraph = await plannedTaskService.getGraph(threadId);
1852
+ if (nextGraph) {
1853
+ await this.syncPlannedTasksToUi(threadId, nextGraph);
1854
+ }
1855
+ }
1856
+ }
1857
+ }
1858
+ catch (error) {
1859
+ this.logger.error('Checkpoint finalization failed', {
1860
+ threadId,
1861
+ checkpointTaskId,
1862
+ error: error instanceof Error ? error.message : String(error),
1863
+ });
1864
+ }
1865
+ await this.schedulePlannedTasks(user, threadId);
1866
+ }
1867
+ async resolveConfirmation(requestingUserId, requestId, request) {
1868
+ const data = toConfirmationData(request);
1539
1869
  if (this.runState.resolvePendingConfirmation(requestingUserId, requestId, data)) {
1540
1870
  this.logger.debug('Resolved pending confirmation (sub-agent HITL)', {
1541
1871
  requestId,
@@ -1558,16 +1888,14 @@ let InstanceAiService = class InstanceAiService {
1558
1888
  });
1559
1889
  return false;
1560
1890
  }
1561
- const { agent, runId, mastraRunId, threadId, user, toolCallId, abortController, tracing } = suspended;
1891
+ const { agent, runId, mastraRunId, threadId, user, toolCallId, abortController, tracing, checkpoint, } = suspended;
1562
1892
  if (user.id !== requestingUserId)
1563
1893
  return false;
1564
1894
  this.runState.activateSuspendedRun(threadId);
1565
1895
  const credentialsPayload = data.nodeCredentials ?? data.credentials;
1566
1896
  const resumeData = {
1567
1897
  approved: data.approved,
1568
- ...(data.credentialId ? { credentialId: data.credentialId } : {}),
1569
1898
  ...(credentialsPayload ? { credentials: credentialsPayload } : {}),
1570
- ...(data.autoSetup ? { autoSetup: data.autoSetup } : {}),
1571
1899
  ...(data.userInput !== undefined ? { userInput: data.userInput } : {}),
1572
1900
  ...(data.domainAccessAction ? { domainAccessAction: data.domainAccessAction } : {}),
1573
1901
  ...(data.action ? { action: data.action } : {}),
@@ -1586,6 +1914,7 @@ let InstanceAiService = class InstanceAiService {
1586
1914
  abortController,
1587
1915
  snapshotStorage: this.dbSnapshotStorage,
1588
1916
  tracing,
1917
+ checkpoint,
1589
1918
  });
1590
1919
  return true;
1591
1920
  }
@@ -1635,6 +1964,7 @@ let InstanceAiService = class InstanceAiService {
1635
1964
  messageGroupId: this.traceContextsByRunId.get(opts.runId)?.messageGroupId,
1636
1965
  createdAt: Date.now(),
1637
1966
  tracing: opts.tracing,
1967
+ checkpoint: opts.checkpoint,
1638
1968
  });
1639
1969
  }
1640
1970
  const intermediateText = await (result.text ?? Promise.resolve(''));
@@ -1725,10 +2055,19 @@ let InstanceAiService = class InstanceAiService {
1725
2055
  if (messageTraceFinalization) {
1726
2056
  await this.maybeFinalizeRunTraceRoot(opts.runId, messageTraceFinalization);
1727
2057
  }
2058
+ if (!this.runState.hasSuspendedRun(opts.threadId)) {
2059
+ if (opts.checkpoint?.isCheckpointFollowUp) {
2060
+ await this.finalizeCheckpointFollowUp(opts.user, opts.threadId, opts.checkpoint.checkpointTaskId);
2061
+ }
2062
+ else {
2063
+ await this.schedulePlannedTasks(opts.user, opts.threadId);
2064
+ }
2065
+ await this.drainPendingCheckpointReentries(opts.user, opts.threadId);
2066
+ }
1728
2067
  }
1729
2068
  }
1730
2069
  spawnBackgroundTask(runId, opts, snapshotStorage, messageGroupIdOverride) {
1731
- this.backgroundTasks.spawn({
2070
+ const outcome = this.backgroundTasks.spawn({
1732
2071
  taskId: opts.taskId,
1733
2072
  threadId: opts.threadId,
1734
2073
  runId,
@@ -1738,6 +2077,8 @@ let InstanceAiService = class InstanceAiService {
1738
2077
  plannedTaskId: opts.plannedTaskId,
1739
2078
  workItemId: opts.workItemId,
1740
2079
  traceContext: opts.traceContext,
2080
+ dedupeKey: opts.dedupeKey,
2081
+ parentCheckpointId: opts.parentCheckpointId,
1741
2082
  run: opts.run,
1742
2083
  onLimitReached: async (errorMessage) => {
1743
2084
  await this.finalizeDetachedTraceRun(opts.taskId, opts.traceContext, {
@@ -1792,25 +2133,88 @@ let InstanceAiService = class InstanceAiService {
1792
2133
  },
1793
2134
  onSettled: async (task) => {
1794
2135
  await this.saveAgentTreeSnapshot(opts.threadId, runId, snapshotStorage, true, task.messageGroupId);
1795
- if (!task.plannedTaskId) {
1796
- const remaining = this.backgroundTasks.getRunningTasks(opts.threadId);
1797
- const hasActiveRun = !!this.runState.getActiveRunId(opts.threadId);
1798
- const hasSuspendedRun = this.runState.hasSuspendedRun(opts.threadId);
1799
- if (remaining.length === 0 && !hasActiveRun && !hasSuspendedRun) {
1800
- const user = this.runState.getThreadUser(opts.threadId);
1801
- if (user) {
1802
- const payload = JSON.stringify({
1803
- role: opts.role,
1804
- status: task.result ? 'completed' : task.error ? 'failed' : 'finished',
1805
- result: task.result ?? undefined,
1806
- error: task.error ?? undefined,
1807
- }, null, 2);
1808
- await this.startInternalFollowUpRun(user, opts.threadId, `<background-task-completed>\n${payload}\n</background-task-completed>\n\n${internal_messages_1.AUTO_FOLLOW_UP_MESSAGE}`, this.runState.getThreadResearchMode(opts.threadId), task.messageGroupId);
1809
- }
2136
+ if (task.plannedTaskId)
2137
+ return;
2138
+ const parentCheckpointId = task.parentCheckpointId;
2139
+ if (parentCheckpointId) {
2140
+ const user = this.runState.getThreadUser(opts.threadId);
2141
+ if (!user) {
2142
+ this.queuePendingCheckpointReentry(opts.threadId, parentCheckpointId);
2143
+ return;
2144
+ }
2145
+ const reentered = await this.maybeReenterParentCheckpoint(user, opts.threadId, task);
2146
+ if (!reentered) {
2147
+ this.queuePendingCheckpointReentry(opts.threadId, parentCheckpointId);
2148
+ }
2149
+ return;
2150
+ }
2151
+ const remaining = this.backgroundTasks.getRunningTasks(opts.threadId);
2152
+ const hasActiveRun = !!this.runState.getActiveRunId(opts.threadId);
2153
+ const hasSuspendedRun = this.runState.hasSuspendedRun(opts.threadId);
2154
+ if (remaining.length === 0 && !hasActiveRun && !hasSuspendedRun) {
2155
+ const user = this.runState.getThreadUser(opts.threadId);
2156
+ if (user) {
2157
+ const payload = JSON.stringify({
2158
+ role: opts.role,
2159
+ status: task.result ? 'completed' : task.error ? 'failed' : 'finished',
2160
+ result: task.result ?? undefined,
2161
+ outcome: task.outcome ?? undefined,
2162
+ error: task.error ?? undefined,
2163
+ }, null, 2);
2164
+ await this.startInternalFollowUpRun(user, opts.threadId, `<background-task-completed>\n${payload}\n</background-task-completed>\n\n${internal_messages_1.AUTO_FOLLOW_UP_MESSAGE}`, this.runState.getThreadResearchMode(opts.threadId), task.messageGroupId);
1810
2165
  }
1811
2166
  }
1812
2167
  },
1813
2168
  });
2169
+ if (outcome.status === 'started') {
2170
+ return { status: 'started', taskId: outcome.task.taskId, agentId: outcome.task.agentId };
2171
+ }
2172
+ if (outcome.status === 'duplicate') {
2173
+ this.logger.warn('Background task dispatch deduped — task already in flight', {
2174
+ threadId: opts.threadId,
2175
+ requestedTaskId: opts.taskId,
2176
+ existingTaskId: outcome.existing.taskId,
2177
+ plannedTaskId: opts.dedupeKey?.plannedTaskId,
2178
+ workflowId: opts.dedupeKey?.workflowId,
2179
+ role: opts.role,
2180
+ });
2181
+ void this.finalizeDetachedTraceRun(opts.taskId, opts.traceContext, {
2182
+ status: 'cancelled',
2183
+ outputs: {
2184
+ taskId: opts.taskId,
2185
+ agentId: opts.agentId,
2186
+ role: opts.role,
2187
+ deduped_to: outcome.existing.taskId,
2188
+ },
2189
+ metadata: {
2190
+ deduped: true,
2191
+ existing_task_id: outcome.existing.taskId,
2192
+ ...(opts.plannedTaskId ? { planned_task_id: opts.plannedTaskId } : {}),
2193
+ ...(opts.workItemId ? { work_item_id: opts.workItemId } : {}),
2194
+ },
2195
+ });
2196
+ this.eventBus.publish(opts.threadId, {
2197
+ type: 'agent-completed',
2198
+ runId,
2199
+ agentId: opts.agentId,
2200
+ payload: {
2201
+ role: opts.role,
2202
+ result: '',
2203
+ error: `Deduped: task already in flight as ${outcome.existing.taskId}`,
2204
+ },
2205
+ });
2206
+ return {
2207
+ status: 'duplicate',
2208
+ existing: {
2209
+ taskId: outcome.existing.taskId,
2210
+ agentId: outcome.existing.agentId,
2211
+ role: outcome.existing.role,
2212
+ plannedTaskId: outcome.existing.plannedTaskId,
2213
+ workItemId: outcome.existing.workItemId,
2214
+ },
2215
+ };
2216
+ }
2217
+ return { status: 'limit-reached' };
1814
2218
  }
1815
2219
  async buildMessageWithRunningTasks(threadId, message) {
1816
2220
  return await (0, instance_ai_1.enrichMessageWithBackgroundTasks)(message, this.backgroundTasks.getRunningTasks(threadId), {
@@ -1853,6 +2257,14 @@ let InstanceAiService = class InstanceAiService {
1853
2257
  });
1854
2258
  }
1855
2259
  async reapAiTemporaryFromRun(threadId, user, createdWorkflowIds) {
2260
+ const runningTaskCount = this.backgroundTasks.getRunningTasks(threadId).length;
2261
+ if (runningTaskCount > 0) {
2262
+ this.logger.debug('Deferring AI-builder temporary workflow cleanup until tasks settle', {
2263
+ threadId,
2264
+ runningTaskCount,
2265
+ });
2266
+ return [];
2267
+ }
1856
2268
  let markedWorkflows = [];
1857
2269
  try {
1858
2270
  markedWorkflows = await this.aiBuilderTemporaryWorkflowRepository.findByThread(threadId);
@@ -2100,6 +2512,7 @@ exports.InstanceAiService = InstanceAiService = __decorate([
2100
2512
  source_control_preferences_service_ee_1.SourceControlPreferencesService,
2101
2513
  telemetry_1.Telemetry,
2102
2514
  db_1.UserRepository,
2103
- db_1.AiBuilderTemporaryWorkflowRepository])
2515
+ db_1.AiBuilderTemporaryWorkflowRepository,
2516
+ n8n_core_1.ErrorReporter])
2104
2517
  ], InstanceAiService);
2105
2518
  //# sourceMappingURL=instance-ai.service.js.map