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.
- package/dist/build.tsbuildinfo +1 -1
- package/dist/chat/chat-execution-manager.js +7 -1
- package/dist/chat/chat-execution-manager.js.map +1 -1
- package/dist/collaboration/collaboration.service.d.ts +1 -0
- package/dist/collaboration/collaboration.service.js +31 -0
- package/dist/collaboration/collaboration.service.js.map +1 -1
- package/dist/commands/execute.d.ts +2 -2
- package/dist/commands/export/credentials.d.ts +2 -2
- package/dist/commands/export/credentials.js +1 -1
- package/dist/commands/export/credentials.js.map +1 -1
- package/dist/commands/export/workflow.d.ts +4 -4
- package/dist/commands/import/credentials.d.ts +12 -2
- package/dist/commands/import/credentials.js +89 -11
- package/dist/commands/import/credentials.js.map +1 -1
- package/dist/commands/import/workflow.d.ts +2 -2
- package/dist/commands/ttwf/generate.d.ts +3 -3
- package/dist/controllers/e2e.controller.js +1 -1
- package/dist/controllers/e2e.controller.js.map +1 -1
- package/dist/controllers/oauth/oauth2-credential.controller.d.ts +6 -4
- package/dist/controllers/oauth/oauth2-credential.controller.js +12 -5
- package/dist/controllers/oauth/oauth2-credential.controller.js.map +1 -1
- package/dist/credentials/credentials.controller.js +1 -1
- package/dist/credentials/credentials.controller.js.map +1 -1
- package/dist/credentials/credentials.service.d.ts +2 -2
- package/dist/credentials/credentials.service.ee.js +2 -2
- package/dist/credentials/credentials.service.ee.js.map +1 -1
- package/dist/credentials/credentials.service.js +13 -16
- package/dist/credentials/credentials.service.js.map +1 -1
- package/dist/credentials/dynamic-credentials-proxy.js +1 -1
- package/dist/credentials/dynamic-credentials-proxy.js.map +1 -1
- package/dist/credentials-helper.d.ts +1 -0
- package/dist/credentials-helper.js +12 -4
- package/dist/credentials-helper.js.map +1 -1
- package/dist/credentials-overwrites.js +2 -2
- package/dist/credentials-overwrites.js.map +1 -1
- package/dist/evaluation.ee/test-runner/evaluation-metrics.ee.d.ts +5 -0
- package/dist/evaluation.ee/test-runner/evaluation-metrics.ee.js +22 -12
- package/dist/evaluation.ee/test-runner/evaluation-metrics.ee.js.map +1 -1
- package/dist/evaluation.ee/test-runner/test-runner.service.ee.d.ts +4 -2
- package/dist/evaluation.ee/test-runner/test-runner.service.ee.js +152 -89
- package/dist/evaluation.ee/test-runner/test-runner.service.ee.js.map +1 -1
- package/dist/evaluation.ee/test-runs.controller.ee.d.ts +8 -2
- package/dist/evaluation.ee/test-runs.controller.ee.js +31 -5
- package/dist/evaluation.ee/test-runs.controller.ee.js.map +1 -1
- package/dist/eventbus/event-message-classes/index.d.ts +3 -2
- package/dist/eventbus/event-message-classes/index.js +11 -1
- package/dist/eventbus/event-message-classes/index.js.map +1 -1
- package/dist/eventbus/message-event-bus/message-event-bus.d.ts +5 -2
- package/dist/eventbus/message-event-bus/message-event-bus.js +101 -73
- package/dist/eventbus/message-event-bus/message-event-bus.js.map +1 -1
- package/dist/eventbus/message-event-bus-writer/message-event-bus-log-writer.d.ts +3 -0
- package/dist/eventbus/message-event-bus-writer/message-event-bus-log-writer.js +3 -1
- package/dist/eventbus/message-event-bus-writer/message-event-bus-log-writer.js.map +1 -1
- package/dist/eventbus/message-event-bus-writer/resolve-event-log-path.d.ts +12 -0
- package/dist/eventbus/message-event-bus-writer/resolve-event-log-path.js +34 -0
- package/dist/eventbus/message-event-bus-writer/resolve-event-log-path.js.map +1 -0
- package/dist/execution-lifecycle/execute-error-workflow.js +1 -1
- package/dist/execution-lifecycle/execute-error-workflow.js.map +1 -1
- package/dist/executions/execution-recovery.service.d.ts +1 -1
- package/dist/executions/execution-recovery.service.js +11 -6
- package/dist/executions/execution-recovery.service.js.map +1 -1
- package/dist/executions/execution.service.d.ts +7 -2
- package/dist/executions/execution.service.js +18 -1
- package/dist/executions/execution.service.js.map +1 -1
- package/dist/executions/executions.controller.d.ts +1 -3
- package/dist/executions/executions.controller.js +3 -17
- package/dist/executions/executions.controller.js.map +1 -1
- package/dist/instance-settings-loader/instance-settings-loader.service.d.ts +3 -1
- package/dist/instance-settings-loader/instance-settings-loader.service.js +6 -2
- package/dist/instance-settings-loader/instance-settings-loader.service.js.map +1 -1
- package/dist/instance-settings-loader/loaders/mcp-settings.loader.d.ts +10 -0
- package/dist/instance-settings-loader/loaders/mcp-settings.loader.js +42 -0
- package/dist/instance-settings-loader/loaders/mcp-settings.loader.js.map +1 -0
- package/dist/instance-settings-loader/loaders/sso.instance-settings-loader.js +9 -4
- package/dist/instance-settings-loader/loaders/sso.instance-settings-loader.js.map +1 -1
- package/dist/mfa/mfa.service.d.ts +2 -2
- package/dist/mfa/mfa.service.js +11 -10
- package/dist/mfa/mfa.service.js.map +1 -1
- package/dist/modules/chat-hub/chat-hub-extractor.js +1 -1
- package/dist/modules/chat-hub/chat-hub-extractor.js.map +1 -1
- package/dist/modules/chat-hub/chat-hub-workflow.service.d.ts +1 -1
- package/dist/modules/chat-hub/chat-hub-workflow.service.js +4 -4
- package/dist/modules/chat-hub/chat-hub-workflow.service.js.map +1 -1
- package/dist/modules/community-packages/community-node-types.service.js +3 -1
- package/dist/modules/community-packages/community-node-types.service.js.map +1 -1
- package/dist/modules/dynamic-credentials.ee/credential-resolvers/n8n-credential-resolver.js +2 -2
- package/dist/modules/dynamic-credentials.ee/credential-resolvers/n8n-credential-resolver.js.map +1 -1
- package/dist/modules/dynamic-credentials.ee/credential-resolvers/oauth-credential-resolver.js +2 -2
- package/dist/modules/dynamic-credentials.ee/credential-resolvers/oauth-credential-resolver.js.map +1 -1
- package/dist/modules/dynamic-credentials.ee/credential-resolvers/slack-credential-resolver.js +2 -2
- package/dist/modules/dynamic-credentials.ee/credential-resolvers/slack-credential-resolver.js.map +1 -1
- package/dist/modules/dynamic-credentials.ee/dynamic-credentials.controller.js +2 -2
- package/dist/modules/dynamic-credentials.ee/dynamic-credentials.controller.js.map +1 -1
- package/dist/modules/dynamic-credentials.ee/services/credential-check-proxy.service.js +1 -1
- package/dist/modules/dynamic-credentials.ee/services/credential-check-proxy.service.js.map +1 -1
- package/dist/modules/dynamic-credentials.ee/services/credential-resolver-workflow.service.js +1 -1
- package/dist/modules/dynamic-credentials.ee/services/credential-resolver-workflow.service.js.map +1 -1
- package/dist/modules/dynamic-credentials.ee/services/credential-resolver.service.js +14 -14
- package/dist/modules/dynamic-credentials.ee/services/credential-resolver.service.js.map +1 -1
- package/dist/modules/dynamic-credentials.ee/services/dynamic-credential-storage.service.js +1 -1
- package/dist/modules/dynamic-credentials.ee/services/dynamic-credential-storage.service.js.map +1 -1
- package/dist/modules/dynamic-credentials.ee/services/dynamic-credential.service.js +4 -4
- package/dist/modules/dynamic-credentials.ee/services/dynamic-credential.service.js.map +1 -1
- package/dist/modules/encryption-key-manager/encryption-bootstrap.service.d.ts +6 -1
- package/dist/modules/encryption-key-manager/encryption-bootstrap.service.js +14 -2
- package/dist/modules/encryption-key-manager/encryption-bootstrap.service.js.map +1 -1
- package/dist/modules/encryption-key-manager/encryption-key.controller.js +1 -0
- package/dist/modules/encryption-key-manager/encryption-key.controller.js.map +1 -1
- package/dist/modules/encryption-key-manager/key-manager.service.d.ts +2 -1
- package/dist/modules/encryption-key-manager/key-manager.service.js +24 -5
- package/dist/modules/encryption-key-manager/key-manager.service.js.map +1 -1
- package/dist/modules/external-secrets.ee/constants.d.ts +1 -0
- package/dist/modules/external-secrets.ee/constants.js +2 -1
- package/dist/modules/external-secrets.ee/constants.js.map +1 -1
- package/dist/modules/external-secrets.ee/external-secrets-manager.ee.js +4 -4
- package/dist/modules/external-secrets.ee/external-secrets-manager.ee.js.map +1 -1
- package/dist/modules/external-secrets.ee/secrets-cache.service.d.ts +1 -0
- package/dist/modules/external-secrets.ee/secrets-cache.service.js +18 -1
- package/dist/modules/external-secrets.ee/secrets-cache.service.js.map +1 -1
- package/dist/modules/external-secrets.ee/secrets-providers-connections.controller.ee.js +3 -3
- package/dist/modules/external-secrets.ee/secrets-providers-connections.controller.ee.js.map +1 -1
- package/dist/modules/external-secrets.ee/secrets-providers-connections.service.ee.d.ts +1 -1
- package/dist/modules/external-secrets.ee/secrets-providers-connections.service.ee.js +15 -13
- package/dist/modules/external-secrets.ee/secrets-providers-connections.service.ee.js.map +1 -1
- package/dist/modules/external-secrets.ee/secrets-providers-project.controller.ee.js +3 -3
- package/dist/modules/external-secrets.ee/secrets-providers-project.controller.ee.js.map +1 -1
- package/dist/modules/external-secrets.ee/settings-store.service.js +6 -6
- package/dist/modules/external-secrets.ee/settings-store.service.js.map +1 -1
- package/dist/modules/insights/insights-collection.service.js +7 -1
- package/dist/modules/insights/insights-collection.service.js.map +1 -1
- package/dist/modules/insights/insights-pruning.service.d.ts +2 -4
- package/dist/modules/insights/insights-pruning.service.js +13 -10
- package/dist/modules/insights/insights-pruning.service.js.map +1 -1
- package/dist/modules/insights/insights.config.js +2 -1
- package/dist/modules/insights/insights.config.js.map +1 -1
- package/dist/modules/insights/insights.constants.d.ts +2 -0
- package/dist/modules/insights/insights.constants.js +3 -1
- package/dist/modules/insights/insights.constants.js.map +1 -1
- package/dist/modules/insights/insights.service.js +1 -3
- package/dist/modules/insights/insights.service.js.map +1 -1
- package/dist/modules/instance-ai/compaction.service.d.ts +7 -2
- package/dist/modules/instance-ai/compaction.service.js +17 -17
- package/dist/modules/instance-ai/compaction.service.js.map +1 -1
- package/dist/modules/instance-ai/instance-ai-settings.service.js +4 -4
- package/dist/modules/instance-ai/instance-ai-settings.service.js.map +1 -1
- package/dist/modules/instance-ai/instance-ai.adapter.service.d.ts +38 -1
- package/dist/modules/instance-ai/instance-ai.adapter.service.js +179 -60
- package/dist/modules/instance-ai/instance-ai.adapter.service.js.map +1 -1
- package/dist/modules/instance-ai/instance-ai.controller.d.ts +2 -2
- package/dist/modules/instance-ai/instance-ai.controller.js +7 -17
- package/dist/modules/instance-ai/instance-ai.controller.js.map +1 -1
- package/dist/modules/instance-ai/instance-ai.service.d.ts +15 -4
- package/dist/modules/instance-ai/instance-ai.service.js +489 -76
- package/dist/modules/instance-ai/instance-ai.service.js.map +1 -1
- package/dist/modules/instance-ai/storage/typeorm-memory-storage.js +11 -1
- package/dist/modules/instance-ai/storage/typeorm-memory-storage.js.map +1 -1
- package/dist/modules/instance-ai/web-research/fetch-and-extract.d.ts +3 -1
- package/dist/modules/instance-ai/web-research/fetch-and-extract.js +13 -11
- package/dist/modules/instance-ai/web-research/fetch-and-extract.js.map +1 -1
- package/dist/modules/instance-ai/web-research/index.d.ts +0 -1
- package/dist/modules/instance-ai/web-research/index.js +1 -3
- package/dist/modules/instance-ai/web-research/index.js.map +1 -1
- package/dist/modules/instance-registry/checks/check.service.d.ts +43 -0
- package/dist/modules/instance-registry/checks/check.service.js +248 -0
- package/dist/modules/instance-registry/checks/check.service.js.map +1 -0
- package/dist/modules/instance-registry/checks/hostid-clash.check.d.ts +8 -0
- package/dist/modules/instance-registry/checks/hostid-clash.check.js +68 -0
- package/dist/modules/instance-registry/checks/hostid-clash.check.js.map +1 -0
- package/dist/modules/instance-registry/checks/index.d.ts +4 -0
- package/dist/modules/instance-registry/checks/index.js +7 -0
- package/dist/modules/instance-registry/checks/index.js.map +1 -0
- package/dist/modules/instance-registry/checks/lifecycle.check.d.ts +8 -0
- package/dist/modules/instance-registry/checks/lifecycle.check.js +52 -0
- package/dist/modules/instance-registry/checks/lifecycle.check.js.map +1 -0
- package/dist/modules/instance-registry/checks/split-brain.check.d.ts +8 -0
- package/dist/modules/instance-registry/checks/split-brain.check.js +67 -0
- package/dist/modules/instance-registry/checks/split-brain.check.js.map +1 -0
- package/dist/modules/instance-registry/checks/version-mismatch.check.d.ts +8 -0
- package/dist/modules/instance-registry/checks/version-mismatch.check.js +55 -0
- package/dist/modules/instance-registry/checks/version-mismatch.check.js.map +1 -0
- package/dist/modules/instance-registry/instance-registry.controller.d.ts +3 -1
- package/dist/modules/instance-registry/instance-registry.controller.js +41 -5
- package/dist/modules/instance-registry/instance-registry.controller.js.map +1 -1
- package/dist/modules/instance-registry/instance-registry.module.js +3 -9
- package/dist/modules/instance-registry/instance-registry.module.js.map +1 -1
- package/dist/modules/ldap.ee/helpers.ee.js +1 -1
- package/dist/modules/ldap.ee/helpers.ee.js.map +1 -1
- package/dist/modules/ldap.ee/ldap.service.ee.js +2 -2
- package/dist/modules/ldap.ee/ldap.service.ee.js.map +1 -1
- package/dist/modules/mcp/dto/update-workflows-availability.dto.d.ts +15 -0
- package/dist/modules/mcp/dto/update-workflows-availability.dto.js +14 -0
- package/dist/modules/mcp/dto/update-workflows-availability.dto.js.map +1 -0
- package/dist/modules/mcp/mcp-oauth-service.d.ts +6 -0
- package/dist/modules/mcp/mcp-oauth-service.js +15 -3
- package/dist/modules/mcp/mcp-oauth-service.js.map +1 -1
- package/dist/modules/mcp/mcp-oauth-token.service.d.ts +1 -0
- package/dist/modules/mcp/mcp-oauth-token.service.js +3 -0
- package/dist/modules/mcp/mcp-oauth-token.service.js.map +1 -1
- package/dist/modules/mcp/mcp.controller.d.ts +2 -0
- package/dist/modules/mcp/mcp.controller.js +49 -11
- package/dist/modules/mcp/mcp.controller.js.map +1 -1
- package/dist/modules/mcp/mcp.errors.d.ts +6 -0
- package/dist/modules/mcp/mcp.errors.js +12 -1
- package/dist/modules/mcp/mcp.errors.js.map +1 -1
- package/dist/modules/mcp/mcp.module.d.ts +1 -0
- package/dist/modules/mcp/mcp.module.js +3 -1
- package/dist/modules/mcp/mcp.module.js.map +1 -1
- package/dist/modules/mcp/mcp.oauth-clients.controller.d.ts +2 -1
- package/dist/modules/mcp/mcp.oauth-clients.controller.js +10 -0
- package/dist/modules/mcp/mcp.oauth-clients.controller.js.map +1 -1
- package/dist/modules/mcp/mcp.oauth.controller.js +20 -1
- package/dist/modules/mcp/mcp.oauth.controller.js.map +1 -1
- package/dist/modules/mcp/mcp.service.js +3 -0
- package/dist/modules/mcp/mcp.service.js.map +1 -1
- package/dist/modules/mcp/mcp.settings.controller.d.ts +11 -12
- package/dist/modules/mcp/mcp.settings.controller.js +19 -50
- package/dist/modules/mcp/mcp.settings.controller.js.map +1 -1
- package/dist/modules/mcp/mcp.settings.service.d.ts +30 -2
- package/dist/modules/mcp/mcp.settings.service.js +165 -2
- package/dist/modules/mcp/mcp.settings.service.js.map +1 -1
- package/dist/modules/mcp/tools/search-executions.tool.d.ts +16 -0
- package/dist/modules/mcp/tools/search-executions.tool.js +140 -0
- package/dist/modules/mcp/tools/search-executions.tool.js.map +1 -0
- package/dist/modules/mcp/tools/workflow-builder/get-workflow-node-types.tool.d.ts +2 -2
- package/dist/modules/oauth-jwe/oauth-jwe-decrypt.service.d.ts +7 -0
- package/dist/modules/oauth-jwe/oauth-jwe-decrypt.service.js +48 -0
- package/dist/modules/oauth-jwe/oauth-jwe-decrypt.service.js.map +1 -0
- package/dist/modules/oauth-jwe/oauth-jwe-key.service.d.ts +31 -0
- package/dist/modules/oauth-jwe/oauth-jwe-key.service.js +174 -0
- package/dist/modules/oauth-jwe/oauth-jwe-key.service.js.map +1 -0
- package/dist/modules/oauth-jwe/oauth-jwe.config.d.ts +3 -0
- package/dist/modules/oauth-jwe/oauth-jwe.config.js +27 -0
- package/dist/modules/oauth-jwe/oauth-jwe.config.js.map +1 -0
- package/dist/modules/oauth-jwe/oauth-jwe.constants.d.ts +9 -0
- package/dist/modules/oauth-jwe/oauth-jwe.constants.js +15 -0
- package/dist/modules/oauth-jwe/oauth-jwe.constants.js.map +1 -0
- package/dist/modules/oauth-jwe/oauth-jwe.controller.d.ts +10 -0
- package/dist/modules/oauth-jwe/oauth-jwe.controller.js +60 -0
- package/dist/modules/oauth-jwe/oauth-jwe.controller.js.map +1 -0
- package/dist/modules/oauth-jwe/oauth-jwe.module.d.ts +8 -0
- package/dist/modules/oauth-jwe/oauth-jwe.module.js +70 -0
- package/dist/modules/oauth-jwe/oauth-jwe.module.js.map +1 -0
- package/dist/modules/oauth-jwe/oauth-jwe.schemas.d.ts +131 -0
- package/dist/modules/oauth-jwe/oauth-jwe.schemas.js +34 -0
- package/dist/modules/oauth-jwe/oauth-jwe.schemas.js.map +1 -0
- package/dist/modules/oauth-jwe/oauth-jwe.utils.d.ts +4 -0
- package/dist/modules/oauth-jwe/oauth-jwe.utils.js +27 -0
- package/dist/modules/oauth-jwe/oauth-jwe.utils.js.map +1 -0
- package/dist/modules/source-control.ee/source-control-export.service.ee.js +1 -1
- package/dist/modules/source-control.ee/source-control-export.service.ee.js.map +1 -1
- package/dist/modules/source-control.ee/source-control-import.service.ee.js +6 -6
- package/dist/modules/source-control.ee/source-control-import.service.ee.js.map +1 -1
- package/dist/modules/source-control.ee/source-control-preferences.service.ee.js +6 -6
- package/dist/modules/source-control.ee/source-control-preferences.service.ee.js.map +1 -1
- package/dist/modules/sso-oidc/oidc.service.ee.js +2 -2
- package/dist/modules/sso-oidc/oidc.service.ee.js.map +1 -1
- package/dist/modules/sso-saml/saml.service.ee.js +6 -6
- package/dist/modules/sso-saml/saml.service.ee.js.map +1 -1
- package/dist/oauth/oauth-jwe-service.proxy.d.ts +9 -0
- package/dist/oauth/oauth-jwe-service.proxy.js +27 -0
- package/dist/oauth/oauth-jwe-service.proxy.js.map +1 -0
- package/dist/oauth/oauth.service.d.ts +2 -2
- package/dist/oauth/oauth.service.js +13 -12
- package/dist/oauth/oauth.service.js.map +1 -1
- package/dist/posthog/index.d.ts +2 -0
- package/dist/posthog/index.js +16 -0
- package/dist/posthog/index.js.map +1 -1
- package/dist/public-api/v1/handlers/credentials/credentials.service.js +2 -2
- package/dist/public-api/v1/handlers/credentials/credentials.service.js.map +1 -1
- package/dist/services/dynamic-node-parameters.service.d.ts +1 -0
- package/dist/services/dynamic-node-parameters.service.js +29 -12
- package/dist/services/dynamic-node-parameters.service.js.map +1 -1
- package/dist/services/export.service.js +2 -2
- package/dist/services/export.service.js.map +1 -1
- package/dist/services/frontend.service.js +18 -0
- package/dist/services/frontend.service.js.map +1 -1
- package/dist/services/import.service.d.ts +5 -1
- package/dist/services/import.service.js +62 -5
- package/dist/services/import.service.js.map +1 -1
- package/dist/services/redis-client.service.d.ts +6 -5
- package/dist/services/redis-client.service.js +19 -12
- package/dist/services/redis-client.service.js.map +1 -1
- package/dist/services/user.service.js +0 -9
- package/dist/services/user.service.js.map +1 -1
- package/dist/task-runners/task-broker/auth/task-broker-auth.service.d.ts +4 -4
- package/dist/task-runners/task-broker/auth/task-broker-auth.service.js +9 -8
- package/dist/task-runners/task-broker/auth/task-broker-auth.service.js.map +1 -1
- package/dist/task-runners/task-broker/task-broker-server.js +1 -1
- package/dist/task-runners/task-broker/task-broker-server.js.map +1 -1
- package/dist/webhooks/test-webhooks.js +16 -2
- package/dist/webhooks/test-webhooks.js.map +1 -1
- package/dist/workflow-execute-additional-data.js +4 -2
- package/dist/workflow-execute-additional-data.js.map +1 -1
- package/dist/workflows/workflow-finder.service.d.ts +2 -0
- package/dist/workflows/workflow-finder.service.js +12 -1
- package/dist/workflows/workflow-finder.service.js.map +1 -1
- package/dist/workflows/workflows.controller.d.ts +7 -2
- package/dist/workflows/workflows.controller.js +43 -10
- package/dist/workflows/workflows.controller.js.map +1 -1
- package/package.json +30 -28
- package/dist/modules/instance-ai/web-research/ssrf-guard.d.ts +0 -1
- package/dist/modules/instance-ai/web-research/ssrf-guard.js +0 -85
- package/dist/modules/instance-ai/web-research/ssrf-guard.js.map +0 -1
- package/dist/modules/mcp/dto/update-workflow-availability.dto.d.ts +0 -9
- package/dist/modules/mcp/dto/update-workflow-availability.dto.js +0 -11
- 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(
|
|
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,
|
|
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
|
-
|
|
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,
|
|
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
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
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:
|
|
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
|
|
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 (
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
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
|